Utilisation d'une librairie C++ dans Objective-C
Bonjour à tous,
J'annonce : Je ne suis pas expert en Objective-C ni C++ (Voilà ça c'est fait)
Le projet est de communiquer avec des Buzzer sans fils via une interface USB en HID.
J'ai reçu les api en C++ du constructeur, je les ai compilée via CMAKE et intégrée dans un projet via Wokspace.
j'ai bien remplacé le .m par .mm pour la reconnaissance des fichiers .h c++
Ou ça coince :
Methode C++
int API_FUNC rf21x_getHidSerialNumber(int index, char *buffer, int maxLength)
{
std::string str;
if (getHidSerialNumber(index, str) && (maxLength > str.length()))
{
strcpy(buffer, str.c_str());
return 1;
}
return 0;
}
test de la communication en Objective-C :
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
// Insert code here to initialize your application
int i = 0;
char buf[100];
while (rf21x_getHidSerialNumber(i , buf , sizeof(buf))) {
NSLog(@hid: %d - Serial: %s, i, buf);
++i;
}
}
Erreur obtenue :
[NSTaggedPointerString getCharacters:range:]: Range {0, 32} out of bounds; string length 3
Lorsque je j'utilise un programme de test compilé en C++ avec la même boucle while je n'ai pas l'erreur.
Je présume qu'il s'agit d'une erreur de typage entre les variables passées via objective-C
Merci d'avance pour vos réponses.
JiBe.
Réponses
Non, le typage semble correct.
Le message d'erreur est lié à NSString, sauf que tu n'en n'utilises pas, sauf dans NSLog. Ca crashe aussi si tu ne loggues rien ?
Essaie de remplacer NSLog() par printf(). Là , spontanément, je dirais que la chaà®ne n'est pas conclue par un octet nul, ou un truc comme ça.
Ou alors un problème d'encoding.
%s s'attend à une chaà®ne C dans l'encoding par défaut du système (je suppose UTF-8 mais je n'ai pas trouvé l'information.
%S s'attend à une chaine C en UTF-16.
Donc je pense que tu peux essayer %S.
lorsque tu pointes ton fichier source sous Xcode es-tu bien en Type Objective-C++ source pour la compilation ?
@zoc: si je fais une fonction vide ça plante également avec la même erreur.
@ceroce: en remplaçant par printf ou sprintf j'ai également la même erreur.
@FKDEV: le fichier est bien en utf-8.
@xyloweb: j'ai mis l'extension .mm pour objective-c++ ou puis-je vérifier si il le compile bien en objective-c++ ?
la methode dans laquelle ça bloque .
valeur à l'entrée dans la méthode :
Test du jour à n'y rien comprendre :
Dans une app type Command line Tool en C++ ça fonctionne.
Dans une app type Command line Tool en Objective-C++ ça fonctionne.
Dans une app type Cocoa Application en Obective-C++ ça plante.
Erreur:
2015-10-02 14:09:49.632
testBYQ[32479:3933619] -
[NSTaggedPointerString getCharacters:range:]: Range {0, 32} out of bounds; string length 3
T'es sur Mac OS X ?
Renseigne toi quand même sur l'encoding par défaut utilisé pour faire le %s.
Il se pourrait que dans un cas ce soit Mac Roman et dans l'autre UTF-16.
Cela dit avec une chaà®ne en UTF-8, je ne vois pas comment cela pourrait planter car il n'y a qu'un seul 0 à la fin.
Par contre, avec une chaine en entrée en UTF-16 (précédé d'un BOM ou commençant par un caractère dont le code serait supérieur à 255) et un %s qui s'attendrait à de l'UTF-8 (ou du Mac Roman), cela pourrait produire une chaine de longueur 3.
Salut @FKDEV,
Oui je suis sous OSX avec la compatibilité mise pour 10.10.
Si je fais une boucle vide j'ai le même problème (sans le %s)
J'ai mis l'appel à la méthode C++ après un bouton :
L'erreur est plus locace :
2015-10-02 17:51:05.550 testBYQ[33466:4234597] -
[NSTaggedPointerString getCharacters:range:]: Range {0, 32} out of bounds; string length 3
2015-10-02 17:51:05.553 testBYQ[33466:4234597] (
0 CoreFoundation 0x00007fff83d8003c __exceptionPreprocess + 172
1 libobjc.A.dylib 0x00007fff81c8176e objc_exception_throw + 43
2 CoreFoundation 0x00007fff83d7feed +[NSException raise:format:] + 205
3 CoreFoundation 0x00007fff83d27b97 -[NSTaggedPointerString getCharacters:range:] + 263
4 CoreFoundation 0x00007fff83c545b6 __CFStringEncodeByteStream + 3638
5 CoreFoundation 0x00007fff83c2fa6b CFStringGetBytes + 795
6 librf21x-api.dylib 0x0000000100043a60 get_string_property_utf8 + 160
7 librf21x-api.dylib 0x0000000100042119 make_path + 73
8 librf21x-api.dylib 0x0000000100041e3b hid_enumerate + 587
9 librf21x-api.dylib 0x000000010003db22 _ZN3Gsp18getHidSerialNumberEiRNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE + 34
10 librf21x-api.dylib 0x000000010003b88b _Z18getHidSerialNumberiRNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE + 27
11 librf21x-api.dylib 0x000000010002ce0c rf21x_getHidSerialNumber + 252
12 testBYQ 0x00000001000011d8 -[AppDelegate readHid:] + 184
13 libsystem_trace.dylib 0x00007fff83915cd7 _os_activity_initiate + 75
14 AppKit 0x00007fff85aa9eb1 -[NSApplication sendAction:to:from:] + 452
15 AppKit 0x00007fff85abf946 -[NSControl sendAction:to:] + 86
16 AppKit 0x00007fff85abf862 __26-[NSCell _sendActionFrom:]_block_invoke + 131
17 libsystem_trace.dylib 0x00007fff83915cd7 _os_activity_initiate + 75
18 AppKit 0x00007fff85abf7bf -[NSCell _sendActionFrom:] + 144
19 libsystem_trace.dylib 0x00007fff83915cd7 _os_activity_initiate + 75
20 AppKit 0x00007fff85abdcb3 -[NSCell trackMouse:inRect:ofView:untilMouseUp:] + 2821
21 AppKit 0x00007fff85b1634f -[NSButtonCell trackMouse:inRect:ofView:untilMouseUp:] + 770
22 AppKit 0x00007fff85abc366 -[NSControl mouseDown:] + 714
23 AppKit 0x00007fff860262dc -[NSWindow _reallySendEvent:isDelayedEvent:] + 14125
24 AppKit 0x00007fff859b5c86 -[NSWindow sendEvent:] + 470
25 AppKit 0x00007fff859b2212 -[NSApplication sendEvent:] + 2504
26 AppKit 0x00007fff858dbb68 -[NSApplication run] + 711
27 AppKit 0x00007fff85858244 NSApplicationMain + 1832
28 testBYQ 0x0000000100001082 main + 34
29 libdyld.dylib 0x00007fff839845c9 start + 1
30 ? ? ? 0x0000000000000003 0x0 + 3
)
Où vérifier que c'est bien de l'utf-8 qui est utilisé pour la communication entre le code en Objective-C++ et la dylib c++ ?
Au niveau du compilateur ?
ah mais là on voit sur la trace que le problème se produit dans la fonction rf21x_getHidSerialNumber.
Donc peut-être pas un problème Objective-C / C++.
As tu les sources de la librairie ? Notamment de la fonction hid_enumerate.
Oui j'ai les sources.
Mais si ça fonctionne pour les App de type commande line tool, pourquoi ça plante avec une App Cocoa ?
Ben en fait c'est clair en lisant le code de la fonction get_string_property_utf8.
Dans l'appel de la fonction CFStringGetBytes, tu passes str de longueur 3 ("USB") et tu passes en deuxième paramètre un range de longueur de 32 alors qu'il est bien spécifié dans la doc que la longueur du range doit être inférieur à la longueur de str.
range : The range of characters in theString to process. The specified range must not exceed the length of the string.
Et on voit bien les valeurs 32 et 3 dans l'erreur:
Range {0, 32} out of bounds; string length 3
get_string_property_utf8 fait partie de l'api que j'ai reçu du constructeur.
Ce que je ne m'explique toujours pas, c'est que dans un app command line C++ ou Objective-C++ ça fonctionne et pas dans une app Cocoa.
Comment tracer avec xcode pour comparer le processus des différentes applications ?