6

I'm trying to create a macro definition that can emit C++ or Objective-C depending on context but can't seem to construct an NSString inside a macro easily. The C++ version is simple because it uses regular strings, but making one that emits NSString is proving tricky:

#define FOO(x) bar(@##x)

The intended result is to convert a string argument to an NSString argument by prefixing with @:

FOO("x")
// => bar(@"x")

What I get instead is an error that prevents compilation:

Pasting formed '@"x"', an invalid preprocessing token

3 Answers 3

5
NSString *x = @"text";

Equals:

NSString *x = CFSTR("text");

PS NSString* and CFStringRef and __CFString* and also NSCFStringRef are all the same: Toll-Free Bridged Types

Sign up to request clarification or add additional context in comments.

5 Comments

CFSTR is promising but it's a CFStringRef and not an NSString*.
@tadman they are one and the same, and are toll-free-bridged.
I'm getting "Incompatible pointer types passing 'CFStringRef' (aka const struct __CFString *) to parameter of type NSString*" when trying this.
@tadman You can cast CFSTR to NSString*, it's toll-free bridged.
The definition that worked: #define AS_NSSTRING(x) ((NSString*)CFSTR(x))
3

You cannot use ## to concatenate elements unless they form a valid preprocessing token together, but you can call NSString's constructor that takes a C string, like this:

#define FOO(x) [NSString stringWithUTF8String:(x)]

3 Comments

Is that going to be something that has to be de-allocated later, unlike @"..." is static, right?
@tadman This produces an autoreleased string, you do not own it unless you retain it.
Should be stringWithUTF8String:, instead.
3

Um, why not this:

#define FOO(x) bar(@x)

?

There's no need to do token pasting or stringifying or anything weird. You just want what's in the argument list at the substitution point to be preceded by an @ sign. So just do that.

3 Comments

only works if x is in quotes. Sometimes that is not desirable. For example: #define CASE_TO_NAME(x) case x: return (NSString*) CFSTR(x); break then a switch statement switch (val) { CASE_TO_NAME(foo); CASE_TO_NAME(bar); // etc. }
Sure, but that's not what the question was about. And your example will break because it doesn't stringify x in CFSTR(x).
My example is fixed when you change to CFSTR(#x), which should be obvious. (Why can't I edit my comment?!)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.