Create constant NSString from constant CFStringRef - nsstring

I am attempting to create a Cocoa Framework that is an object-oriented wrapper around a procedural framework written in the Core Foundation. The procedural framework has a number of constants that are all defined as extern CFStringRef constantName.
How should I create NSString constants that directly map to the procedural constants so that in my framework I can simply cast the NSString constant to the CFStringRef constant within the framework such that the developer using my framework does not need to be aware of the casts himself.
Every thing that I have tried results in the compiler error Initializer element is not constant. This is the pattern I would like to use:
Constants.h:
extern NSString * myConstant
Constants.m:
#import "Constants.h"
NSString *myConstant = ConstantFromCFStringRef;
I am successfully declaring constant values with NSString in Constants.m using NSString *aConstant = #"someStringLiteral" but in this case, I want to have the same value as the CFStringRefs that I cannot ignore.

Have you tried:
NSString * myconstant = (NSString *)constantName;
You can find the same answer here: How to convert CFStringRef to NSString? and there: CocoaDev: CFStringRef.
Indeed Apple has already solved your problem. This is called Toll Free Bridging.

Related

cannot convert cont char* to LPCWSTR

I am stuck with an error in QT compiler however it works fine with VS2010. the error states that
I have seen other posts related to the same error but non has resolved my problem in QT. I have tried _T,L or TEXT but still not working
bq. error: C2664: 'HANDLE
LoadImageW(HINSTANCE,LPCWSTR,UINT,int,int,UINT)' : cannot convert
argument 2 from 'const char *' to 'LPCWSTR' Types pointed to are
unrelated; conversion requires reinterpret_cast, C-style cast or
function-style cast
my code is as below
Bitmap::Bitmap(std::string const& file_name) {
bitmap_ = static_cast<HBITMAP>(::LoadImage(0, file_name.c_str(), IMAGE_BITMAP,0,0,LR_LOADFROMFILE|LR_CREATEDIBSECTION));
}
please share if you have any idea to resolve this
Qt does not include a compiler. On Windows you're probably either compiling with mingw or Visual C++. Either way, the issue is that you're calling a function that expects a wide character string but you're trying to hand it an 8-bit character string.
For compatibility reasons, Win32 uses a different set of API functions if you have _UNICODE defined. In your case, you do have _UNICODE defined. You can continue using the 8-bit std::string but simply change the method from LoadImage() to LoadImageA(). Or if you don't mind changing your Bitmap class, you could switch from std::string to std::wstring to take advantage of Windows' Unicode features.
But perhaps the larger question is why use Win32 to load bitmaps and std::string if you're using Qt? Qt's QImage class and QString class provide a full-featured, cross-platform strings and image loaders. Like any comprehensive framework, Qt works best if you only use external features on an as-needed basis.
I'm not sure if this method is the best, but I've used them on my projects and it works fine, see:
char *source = "Hello world";
WCHAR target[size];
MultiByteToWideChar(CP_ACP, 0, source, -1, target, size);
LPCWSTR final = target;
MessageBox(0, final, TEXT("title"), 0); //Sample usage

Should I release simple NSString in dealloc

I have in .h:
#property (nonatomic,retain) NSString *myString;
In .m:
#synthesize myString;
myString =#"Test";
Do I have to release it in dealloc?
Because sometimes my app crashes due to [myString release], not sure why?
As long as the property is defined with the "retain" attribute, it needs to be released in the dealloc.
ARC (Automatic Reference Counting) in modern Objective C has built-in garbage collection, so releasing and retaining are no longer necessary.

Constant NSString release

NSString *string = #"hello";
1) I keep reading that constant NSString does not get released, but this Apple page mentions:
the compiler makes such object
constants unique on a per-module
basis, and they’re never deallocated,
though you can retain and release them
as you do any other object.
http://developer.apple.com/mac/library/documentation/cocoa/conceptual/strings/Articles/CreatingStrings.html
2) If constant NSString does not get released, would it cause memory problems if used extensively? For example, is this a problem if repeated thousands of times:
NSString *string = #"One";
...
string = #"two";
...
string = #"three";
...
what's a good alternative?
Constant strings are part of you app's binary.
So, you do not need to worry about memory management, as they exist through all the execution and can not be released.

What is the difference among NSString alloc:initWithCString versus stringWithUTF8String?

I thought these two methods were (memory allocation-wise) equivalent, however, I was seeing "out of scope" and "NSCFString" in the debugger if I used what I thought was the convenient method (commented out below) and when I switched to the more explicit method my code stopped crashing! Notice that I am getting the string that is being stored in my container from sqlite3 query.
p = (char*) sqlite3_column_text (queryStmt, 1);
// GUID = (NSString*) [NSString stringWithUTF8String: (p!=NULL) ? p : ""];
GUID = [[NSString alloc] initWithCString:(p!=NULL) ? p : "" encoding:NSUTF8StringEncoding];
Also note, that if I looked at the values in the debugger and printed them with NSLog they looked correct, however, I don't think new memory was allocated and the value copied. Instead the memory pointer was stored - went out of scope - referenced later - crash!
If you need to keep a reference to an object around after a method returns, then you need to take ownership of the object. So, if your variable GUID is an instance variable or some kind of global, you will need to take ownership of the object. If you use the alloc/init method, you have ownership of the object returned since you used alloc. You could just as easily use the stringWithUTF8String: method, but you will need to take ownership explicitly by sending a retain message. So, assuming GUID is some kind of non-method-scoped variable:
GUID = [[NSString stringWithUTF8String:"Some UTF-8 string"] copy];
(either copy or retain can be used here to take ownership, but copy is more common when dealing with strings).
Also, your code may be a little easier to read if you did something like:
GUID = p ? [[NSString stringWithUTF8String:p] copy] : #"";

How do I call Foo(long[][]) (C#) from Managed C++ (old syntax)?

I've got existing C# code with signature of Foo(long[][] longs) which I need to call from Unmanaged C++ (not C++/CLI). I just can't seem to figure out the right combination of __gc[] and __gc* to make the compiler happy.
With C++/CLI, this is straight-forward:
std::vector<__int64> evens;
evens.push_back(2); evens.push_back(4); evens.push_back(6); evens.push_back(8);
std::vector<__int64> odds;
odds.push_back(1); odds.push_back(3); odds.push_back(5); odds.push_back(7);
std::vector<std::vector<__int64> > ints;
ints.push_back(evens); ints.push_back(odds);
array<array<__int64>^>^ mgdInts = gcnew array<array<__int64>^>(ints.size());
for (size_t i = 0; i<ints.size(); ++i)
{
const std::vector<__int64>& slice = ints[i];
mgdInts[i] = gcnew array<__int64>(slice.size());
for (size_t j=0; j<slice.size(); ++j)
mgdInts[i][j] = slice[j];
}
Edit: As I'm using Visual Studio 2008, the "simple" solution is to put the C++/CLI code in its own file and compile with /clr; of course, it would be easier if I didn't have to do this (e.g., other .h files with Managed C++). The C# code can't change as it's auto-generated from a web reference.
Change the signature from this
Foo(long[][] longs)
to this:
Foo(Array longs)
Then when you look at the resulting type library in OleView.exe, you should see:
HRESULT Foo([in] SAFEARRAY(int64) longs);
From C++, that's fairly straight forward to call. You can just Win32 to create a SAFEARRAY, or I suggest include and then use the CComSafeArray wrapper class in ATL.
Even though both C# and C++ have richer array definitions, the interoperability between the two is typically done though the Type Library marshaller, 99% of which is legacy and based on what's "VB Compatible". The only array types that the Type Library marshaller supports is SAFEARRAY, so that's what you get when you follow the normal way of doing all this.
However, COM supports a richer array system (conformant arrays), which C# understands, it's harder to do, and you can't simply regasm your C# DLL and use the resulting type library in your unmanaged C++ program. Some of the techniques require tweaking the C# code with ILDASM. Others require you to keep two definitions of the interface, one in C++ and one in C#, and make sure they're in sync (no way to convert one to the other), then in the IDL for C++ adorn the parameter with size_is, and in C# with MarshalAs. It's kind of a mess and really the only type people do that is if they have an already published legacy interface that they cannot change. If this is your C# code, and you can define the interface, I wouldn't go there. Still, the technique is available. Here's a refernece: http://support.microsoft.com/kb/305990
Expect about a week or so to get through this if you've never done anything like this before.
The solution I came up with is to use List<>.ToArray():
System::Collections::Generic::List<__int64 __gc[]>* mgdInts = new System::Collections::Generic::List<__int64 __gc[]>(ints.size());
for (size_t i = 0; i<ints.size(); ++i)
{
const std::vector<__int64>& slice = ints[i];
__int64 mgdSlice __gc[] = new __int64 __gc[slice.size()];
for (size_t j=0; j<slice.size(); ++j)
mgdSlice[j] = slice[j];
mgdInts->Add(mgdSlice);
}
ClassLibrary1::Class1::Foo(mgdInts->ToArray());

Resources