Objective-C et C++
fouf
Membre
Bonjour.
Dans l'application sur laquelle je travaille, j'utilise des classes C++ qui seront appelées par des objets en Obj-C. Je sais bien que pour utiliser du C++ dans du code Obj-C, il suffit de "passer" en Objective-C++ en modifiant le nom du fichier (extension .mm au lieu de .m).
Le point critique est que je n'ai absolument aucune envie de passer tout les fichiers d'implémentation de mon projet ou presque en .mm. Ne peut on pas se limiter à certains fichier.
Pour être tout à fait clair, j'ai une fonction qui ne prends en argument absolument aucun objet ni en Obj-C ni en C++ mais qui en utilise dans son implémentation. Je déclare alors dans le header associé cette fonction, puis je fais appel à cette fonction dans le fichier .m . Le problème est alors que le linker m'engueule un tout petit peu et me dit qu'il ne trouve pas le symbole associé à la fonction en question. Je change alors le nom du fichier en .m et ca marche alors très très bien.
Ne puis-je pas garder d'une manière ou d'une autre le fichier en Obj-C et non en Obj-C++ ?
Dans l'application sur laquelle je travaille, j'utilise des classes C++ qui seront appelées par des objets en Obj-C. Je sais bien que pour utiliser du C++ dans du code Obj-C, il suffit de "passer" en Objective-C++ en modifiant le nom du fichier (extension .mm au lieu de .m).
Le point critique est que je n'ai absolument aucune envie de passer tout les fichiers d'implémentation de mon projet ou presque en .mm. Ne peut on pas se limiter à certains fichier.
Pour être tout à fait clair, j'ai une fonction qui ne prends en argument absolument aucun objet ni en Obj-C ni en C++ mais qui en utilise dans son implémentation. Je déclare alors dans le header associé cette fonction, puis je fais appel à cette fonction dans le fichier .m . Le problème est alors que le linker m'engueule un tout petit peu et me dit qu'il ne trouve pas le symbole associé à la fonction en question. Je change alors le nom du fichier en .m et ca marche alors très très bien.
Ne puis-je pas garder d'une manière ou d'une autre le fichier en Obj-C et non en Obj-C++ ?
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
En effet le problème est qu'à la compilation de ton fichier de code en fichier objet, les noms des fonctions sont transformés en symboles (name mangling), et :
- autant en C ce mangling n'utilise que le nom de la fonction et le nombre d'octets pris par ses arguments grosso modo (je me rappelle plus es détails mais bon)
- autant en C++ comme on peut surcharger une méthode (avoir une méthode qui a le même nom qu'une autre mais des arguments différents) ou faire de l'encapsulation (et permettre à 2 méthodes de même nom de coexister si elles sont dans deux classes différentes), le name mangling a été adapté en conséquence et n'est donc pas le même qu'en C.
C'est pour ça que quand on souhaite linker entre eux plusieurs fichiers objets (plusieurs fichiers C et C++ chacun compilés de leur côté), pour pouvoir appeler des méthodes de l'un depuis l'autre, il faut cette petite information/directive de [tt]extern "C"[/tt].
A creuser donc.
Je crée une classe DBToto qui a une méthode de classe +totoFaitTonTruc: qui fait appel directement à la fonction totoFaitSonTruc(). Là , tout se passe très bien, mais faire une classe uniquement pour ca je trouve que c'est mal parce que les classes ne sont pas faites pour cela (ce sont les fonctions qui sont chargées de ce type de travail).
Je connais le truc du "extern C" (même si je n'en connaissais pas l'origine, je me coucherais moins bête se soir ... ) et le name mangling permet d'expliquer en détail le message d'erreur que je recevais ("symbol _nomDeLaFonction not found" et non nomDeLaFonction, le name mangling doit rajouter un _). Merci beaucoup AliGator
En tout cas, pour moi faut au moins essayer le extern C :
C'est du moins les deux méthodes les plus "pratique" que j'utilise
Pour les fonctions tu peux soit encadrer toutes tes déclarations avec ce qu'indique aligator, c'est-à -dire extern "C" { }, soit tu peux aussi déclarer les fonctions comme extern "C" une à une. La technique généralement choisie est celle-ci:
Tu mets ça dans ton pch par exemple, ou dans un header que tu importes dans chaque fichier.
puis tu l'utilises comme suit:
Et pour les ivars qui vont être des objets C++ sous le capot, tu peux utiliser void* avec allocation dynamique, ainsi qu'une macro dans le code C++ pour faire un cast faire le vrai type de ta variable en C++.
Exemple: