Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
567 views
in Technique[技术] by (71.8m points)

objective c - fake va_list in ARC

I need to create in an iOS application a fake va_list to pass to a NSString initWithFormat:arguments: function, this is my code:

NSArray *fixedArguments = [[NSArray alloc] initWithArray:arguments]; 

NSRange range = NSMakeRange(0, [fixedArguments count]);

va_list fakeArgList = (va_list)malloc(sizeof(NSString *) * [fixedArguments count]);

__unsafe_unretained id *ptr = (__unsafe_unretained id *)fakeArgList;

[fixedArguments getObjects:ptr range:range];

content = [[NSString alloc] initWithFormat:outputFormat
                                            arguments:(va_list)fakeArgList];
free(fakeArgList);

The compiler complains with this message on the cast line:

error: cast of a non-Objective-C pointer type 'va_list' (aka 'char *') to '__unsafe_unretained id *' is disallowed with ARC

The getObjects:range: function is defined as follows:

- (void)getObjects:(id __unsafe_unretained [])objects range:(NSRange)range;

I've tried everything but still can't get rid of this error...

Is there a solution for creating a fake va_list with ARC enabled? What am i doing wrong?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

EDIT: This no longer works. As foreseen in the initial answer, the ABI appears to have changed out from under this answer

Played around for a bit and got it to work -- Double checked for leaks or abandoned memory and didn't see any.

    NSArray *fixedArguments = [[NSArray alloc] initWithObjects: @"foo", @"bar", @"baz", nil]; 

    NSRange range = NSMakeRange(0, [fixedArguments count]);

    NSMutableData* data = [NSMutableData dataWithLength: sizeof(id) * [fixedArguments count]];    

    [fixedArguments getObjects: (__unsafe_unretained id *)data.mutableBytes range:range];

    NSString* content = [[NSString alloc] initWithFormat: @"1: %@ 2: %@ 3: %@"  arguments: data.mutableBytes];

    NSLog(@"%@", content);

I like to (ab)use NSMutableData like this to get retain/release semantics on an arbitrary chunk of memory -- It's not necessarily relevant to the issue at hand, but it's a neat little trick.

As a note to future readers: Faking up a va_list like this happens to work with the current ABI for MacOS and iOS, but in general it's not portable, and not a good approach.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...