views:

106

answers:

4

I have an Objective-C view controller class, from which I am trying to call a straight-C (not Objective-C) function. I want to pass in a string variable by reference, set its value inside the C function, and then back in my view controller I want to convert this to a normal NSString object.

Since I can't pass in an NSString object directly, I need to create and pass in either a char pointer or a char array, and then convert it to an NSString object after the function returns.

Can anyone point me to a simple code example that shows how to do this? I'm not strong in either Objective-C or regular C, so manipulating strings is extremely difficult for me.

+1  A: 

Check out the following in the NSString docs:

– cStringUsingEncoding:
– getCString:maxLength:encoding:
– UTF8String
+ stringWithCString:encoding:
Nimrod
My main problem is passing a char array into a C function and getting a value back out, so it's more of a C problem than an Objective-C problem.
MusiGenesis
Try char *foo = [myString UTF8String]; char *bar = cfunction(foo); NSString *newString = [NSString stringWithCString:bar encoding:NSUTF8StringEncoding];
Nimrod
+5  A: 

Maybe something like this

bool doSomethingToMyString(const char* originalString, char *buffer, unsigned int size)
{
    bool result = 0;
    if (size >= size_needed)
    {
        sprintf(buffer, "The new content for the string, maybe dependent on the originalString.");
        result = 1;
    }
    return result;
}

...
- (void) objectiveCFunctionOrSomething:(NSString *)originalString
{
    char myString[SIZE];
    if (doSomethingToMyString([originalString UTF8String], myString, SIZE))
    {
        NSString *myNSString = [NSString stringWithCString:myString encoding:NSUTF8StringEncoding];
        // alright!
    }
}

or, you know, something to that effect.

filipe
I think `stringWithCString` is deprecated (not that there's anything wrong with that). :)
MusiGenesis
I'm not sure, but I think `stringWithCString:` is deprecated but `stringWithCString:encoding:` isn't. I may be mistaken though.
filipe
A: 

Well, I got it to work. Here is my C function:

int testPassingChar(char buffer[]) {    
    strcpy(buffer, "ABCDEFGHIJ");
    return 0;
}

And then from Objective-C:

char test[10];
int i;
i = testPassingChar(test);
NSString* str = [[NSString alloc] initWithBytes:test length:sizeof(test) 
    encoding:NSASCIIStringEncoding];
MusiGenesis
You should generally avoid having functions do stuff with passed-in buffers without knowing what size they are. (And by "generally" I really mean "always".)
walkytalky
what walkytalky said. And in your example if you strcpy "ABCDEFGHIJ" into a buffer that is 10 in size, you'll get a buffer overflow from the `"\0"` terminating character.
filipe
@filipe: the above code works with no buffer overflow.
MusiGenesis
@walkytalky: I would indeed prefer to pass in a pointer instead of a pre-allocated buffer, but the above code is the only thing I'm able to get working right now. Also, if I allocate the size of my buffer in the C function, I then have to clean up the memory in Objective-C, which seems odd to me.
MusiGenesis
@MusiGenesis: You most certainly do have a buffer overflow. Whether or not it clobbers something important depends on how the compiler decides to arrange the array on the stack (often, the optimization level will affect this)
rpetrich
@MusiGenesis: The problem of not knowing the length is the same whether you pass in a pointer or a stack-allocated array (although the consequences of overrunning might differ). It's perfectly acceptable to do C-style dynamic allocations with `malloc`/`free` in Objective-C -- there are objecty alternatives if you really want them, but probably superfluous in a case like this. Have your function tell you how much space it needs so you can avoid using a fixed length.
walkytalky
A: 

Why don't you wrap your C function in Objective-C?

-(NSString*)testPassingCharWithStringLength:(int)whateverLength {
     char *test = malloc(sizeof(char) * whateverLength);  
     //do whatever you need to *test here in C
     NSString *returnString = [NSString stringWithUTF8String:test];
     free(test);
     return returnString;
}

...for example...

diatrevolo