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 ?

  • CéroceCéroce Membre, Modérateur

    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.


  • FKDEVFKDEV Membre
    septembre 2015 modifié #4

    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 ?


  • jibejibe Membre
    octobre 2015 modifié #6

    @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 .



    static int get_string_property_utf8(IOHIDDeviceRef device, CFStringRef prop, char *buf, size_t len)
    {
    CFStringRef str = IOHIDDeviceGetProperty(device, prop);

    buf[0] = 0x0000;

    if (str) {
    CFRange range;
    range.location = 0;
    range.length = len;
    CFIndex used_buf_len;
    CFStringGetBytes(str,
    range,
    kCFStringEncodingUTF8,
    (char)'?',
    FALSE,
    (UInt8*)buf,
    len,
    &used_buf_len);
    buf[len-1] = 0x00000000;
    return used_buf_len;
    }
    else
    return 0;

    }

    valeur à  l'entrée dans la méthode :




    buf char * "\x16" 0x00007fff5fbede40
    device IOHIDDeviceRef 0x6080001411e0 0x00006080001411e0
    prop CFStringRef @Transport 0x0000000100046c58
    len size_t 32 32
    str CFStringRef @USB 0x0000000042535535

  • Test du jour à  n'y rien comprendre :


     


    Dans une app type Command line Tool en C++ ça fonctionne.



    #include <iostream>
    #include "rf21x-api.h"

    int main(int argc, const char * argv[]) {
    // insert code here...
    std::cout << "Hello, World!\n";
    char buf[100];
    int i = 0;
    while (rf21x_getHidSerialNumber(i , buf, sizeof(buf))) {
    std::cout << printf("Device %i: serial: %s", i, buf) << std::endl;
    ++i;
    }
    return 0;
    }

    Dans une app type Command line Tool en Objective-C++ ça fonctionne.



    #import <Foundation/Foundation.h>
    #import "rf21x-api.h"

    int main(int argc, const char * argv[]) {
    @autoreleasepool {
    // insert code here...
    NSLog(@Hello, World!);

    char buf[100];
    int i = 0;
    while (rf21x_getHidSerialNumber(i , buf, sizeof(buf))) {

    printf("Device %i: serial: %s\n", i, buf);
    ++i;
    }

    }
    return 0;
    }

    Dans une app type Cocoa Application en Obective-C++ ça plante.



    #import "AppDelegate.h"
    #import "rf21x-api.h"

    @interface AppDelegate ()

    @property (weak) IBOutlet NSWindow *window;
    @end

    @implementation AppDelegate

    - (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
    // Insert code here to initialize your application
    char buf[100];
    int i = 0;
    while (rf21x_getHidSerialNumber(i , buf, sizeof(buf))) {

    printf("Device %i: serial: %s\n", i, buf);
    ++i;
    }

    }

    - (void)applicationWillTerminate:(NSNotification *)aNotification {
    // Insert code here to tear down your application
    }

    @end


    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.

  • jibejibe Membre
    octobre 2015 modifié #10

    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 :



    - (IBAction)readHid:(id)sender {
    char buf[100];
    int i = 0;
    _lblHid.stringValue = @Processing HID device ...;

    while (rf21x_getHidSerialNumber(i , buf, sizeof(buf))) {
    ++i;
    }


    }

    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 ?


  • FKDEVFKDEV Membre
    octobre 2015 modifié #11

    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 ?


Connectez-vous ou Inscrivez-vous pour répondre.