2016-05-18 5 views
1

Ich bin in einer Objective-C-Methode mit verschiedenen NSString s, die ich an eine C-Funktion übergeben möchte. Die C-Funktion benötigt ein struct Objekt be malloc 'd, damit es übergeben werden kann - diese Struktur enthält char Felder. So wird die struct wie folgt definiert:Konvertierung von NSStrings in C-Zeichen und Aufruf einer C-Funktion von Objective-C

struct libannotate_baseManual { 
    char *la_bm_code; // The base code for this manual (pointer to malloc'd memory) 
    char *la_bm_effectiveRevisionId; // The currently effective revision ID (pointer to malloc'd memory or null if none effective) 
    char **la_bm_revisionId; // The null-terminated list of revision IDs in the library for this manual (pointer to malloc'd array of pointers to malloc'd memory) 
}; 

Diese Struktur wird dann in der folgenden C-Funktionsdefinition verwendet:

void libannotate_setManualLibrary(struct libannotate_baseManual **library) { .. 

Also das ist die Funktion, die ich brauche von Objective-C zu nennen.

So habe ich verschiedene NSString s, die ich im Grunde dort übergeben wollen, die Zeichen darstellen - la_bm_code, la_bm_effectiveRevisionId, la_bm_revision. Ich könnte diese in const char s unter Verwendung [NSString UTF8String] konvertieren, aber ich brauche char s, nicht const char s.

Auch ich muss geeignete malloc 's für diese Felder tun, obwohl ich anscheinend nicht sorgen muss, um den Speicher danach zu befreien. C ist nicht meine Stärke, obwohl ich Objective-C gut kenne.

Antwort

3

strdup() ist Ihr Freund hier als das sowohl malloc() s und strcpy() s für Sie in einem einfachen Schritt. Es ist Speicher wird auch freigegeben mit free() und es macht Ihre const char * zu char * Umwandlung für Sie!

NSString *code = ..., *effectiveRevId = ..., *revId = ...; 
struct libannotate_baseManual *abm = malloc(sizeof(struct libannotate_baseManual)); 
abm->la_bm_code = strdup([code UTF8String]); 
abm->la_bm_effectiveRevisionId = strdup([effectiveRevId UTF8String]); 
const unsigned numRevIds = 1; 
abm->la_bm_effectiveRevisionId = malloc(sizeof(char *) * (numRevIds + 1)); 
abm->la_bm_effectiveRevisionId[0] = strdup([revId UTF8String]); 
abm->la_bm_effectiveRevisionId[1] = NULL; 

const unsigned numAbms = 1;  
struct libannotate_baseManual **abms = malloc(sizeof(struct libannotate_baseManual *) * (numAbms + 1)); 
abms[0] = abm; 
abms[1] = NULL; 
libannotate_setManualLibrary(abms); 

Viel Glück, du wirst es brauchen. Es ist eine der schlechtesten Schnittstellen, die ich je gesehen habe.

+0

Das ist fantastisch, danke. Versuche es jetzt. BTW ja - muss eine Reihe von Zeigern übergeben, also auch darauf schauen. –

+0

@LukeSmith Gern geschehen. Code korrigiert. – trojanfoe

+0

Toller Job danke :) –