2012-02-13 3 views
2

J'ai construit un dylib 32 bits pour OS X avec Delphi XE2 Upd. 3. Son nom d'installation utilise @rpath. Toutes les exportations commencent par un trait de soulignement, vérifié avec otool. Les exportations utilisent la convention d'appel "cdecl" dans Delphi..dylib fait avec Delphi XE2 ne peut pas être utilisé par l'application Xcode

Je n'arrive pas à faire fonctionner ce dylib avec une application hôte 32 bits dans Xcode 4.3 fonctionnant sous OS X 10.7.3. Lorsque j'exécute le projet de test depuis Xcode, il s'arrête avec l'appel de lib et dyld_start dans la pile d'appels.

enter image description here

Quand je lance cette application à partir du Finder (à partir du dossier Xcode au sein de la bibliothèque de l'utilisateur), je reçois l'image non trouvé erreur de dyld.

J'ai déjà ajouté une phase de construction de copie, qui copie le dylib (et libcgunwind.1.0.dylib dont il a besoin) dans le répertoire Products. J'ai également défini Runpath Search Paths à @executable_path ou @loader_path, mais en vain.

La méthode est importée via

extern int TestLib(int AInt); 

La bibliothèque est aussi minime qu'il peut obtenir et ne contient que cette unité:

unit LibTestExports; 

uses 
    System.Classes, 
    System.SysUtils; 

function _TestLib(AInt: Integer): Integer; export; cdecl; 
begin 
    Result:= AInt + 2; 
end; 

exports 
    _TestLib; 

end. 

Je suis d'idées sur ce qui en est la cause et comment je peux faire fonctionner ça.

Le projet Xcode et les libs se trouvent ici: http://dl.dropbox.com/u/17403534/CAS4LibTest.zip

MISE À JOUR: Ce problème semble être Lion spécifique! Cela fonctionne très bien dans Snow Leopard 10.6.4 avec Xcode 4.2. (Xcode 4.2 sur Lion entraîne le même problème)

Le même dylib fonctionne également très bien sous Lion lorsqu'il est utilisé par une application FireMonkey (les méthodes sont importées statiquement en utilisant external 'libName').

L'exécution de la même application sous Lion, qui fonctionne très bien sous SnowLeopard, je reçois un rapport de plantage contenant la pile d'appel suivant:

0 ???        0x0013317c 0 + 1257852 
1 libCAS4.dylib     0x00010b5c @DbgEvalFrame + 1648 
2 libCAS4.dylib     0x00010e1a @DbgEvalFrame + 2350 
3 dyld       0x8fe55203 ImageLoaderMachO::doModInitFunctions(ImageLoader::LinkContext const&) + 251 
4 dyld       0x8fe54d68 ImageLoaderMachO::doInitialization(ImageLoader::LinkContext const&) + 64 
5 dyld       0x8fe522c8 ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int, ImageLoader::InitializerTimingList&) + 256 
6 dyld       0x8fe5225e ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int, ImageLoader::InitializerTimingList&) + 150 
7 dyld       0x8fe53268 ImageLoader::runInitializers(ImageLoader::LinkContext const&, ImageLoader::InitializerTimingList&) + 62 
8 dyld       0x8fe47694 dyld::initializeMainExecutable() + 214 
9 dyld       0x8fe4bf99 dyld::_main(macho_header const*, unsigned long, int, char const**, char const**, char const**) + 2238 
10 dyld       0x8fe452ef dyldbootstrap::start(macho_header const*, int, char const**, long, macho_header const*) + 637 
11 dyld       0x8fe45063 _dyld_start + 51 

Solution: soutien Embarcadero est venu maintenant de retour avec une solution de contournement, qui fixe le problème pour moi: dans une copie locale de System.Classes, modifiez la déclaration de GlobalNameSpace: IReadWriteSync à la classe appropriée utilisée dans la section d'initialisation.

+0

nm: objet: objet libLibTest.dylib malformé (table indirecte au décalage 509728 avec une taille de 576, chevauche le contenu de la section au décalage 507904 avec une taille de 67082) ... la bibliothèque de test est-elle valide? – Petesh

+0

J'espère que la bibliothèque est valide, mais je ne sais pas avec certitude. Si ce n'est pas le cas, cela signifierait que Delphi XE2 est gravement endommagé, puisque c'est le code le plus basique transformé en bibliothèque. En fait, j'ai également remarqué que nm pensait que la bibliothèque était invalide, mais a ensuite vu que otool produisait bien les exportations. – msohn

+0

Gardez à l'esprit que nm, otool et dyld utilisent un code différent pour lire les éléments pertinents dans le fichier. La plainte de nm peut être la raison de l'échec de l'invocation dyld. J'ai utilisé IDA pour désassembler l'appel TestLib, et il semble qu'il prenne un int * comme paramètre, pas un int. Cela aurait un effet secondaire de provoquer une violation d'accès lorsqu'il est invoqué; mais il semble que l'erreur se produit avant que (au moment de chargement de la bibliothèque) – Petesh

Répondre

2

La bibliothèque que vous créez a une dépendance implicite sur bplrtl160.dylib, que vous devrez regrouper avec l'application - Vous devez vous assurer que la bibliothèque est créée à l'aide de packages d'exécution.

Il existe une forme de magie d'initialisation qui se produit lorsque vous créez un exécutable avec Delphi XE2 qui ne se produit pas lorsque vous générez l'application sous xcode, ce qui cause le problème; probablement un code d'initialisation qui est lié à l'application qui n'est pas liée lorsqu'elle est créée en tant que bibliothèque.

L'exception réelle que vous obtenez est en:

@[email protected]@IReadWriteSync 

qui se passe à bplrtl160.dylibcharge temps (à savoirvous n'avez même pas à interagir avec la bibliothèque à ce stade). C'est une classe d'interface qui devrait être initialisée au moment du chargement de l'application.

Si vous supprimez les entrées System.SysUtils, System.Classes de la clause uses du fichier de bibliothèque, la bibliothèque sera chargée; mais cela signifie que toute bibliothèque que vous construisez à partir de XE2 ne peut pas utiliser le code classes et sysutils; ce qui le rend un peu moins adapté à l'utilisation.

Comme pour le correctif; Je ne sais pas. Il n'y a peut-être pas de solution du tout.

+0

Merci beaucoup, j'ai pu le faire tourner avec une lib qui n'a pas d'unités RTL dans la clause uses. Mais comme vous l'avez mentionné, cela n'a pas beaucoup d'utilité. – msohn

+0

Si j'accepte les paquets d'exécution, alors j'ai une dépendance sur le paquet RTL, c'est très clair. Mais pourquoi je l'ai, si je compile le RTL dans le dylib? Si je ne compile pas à l'aide de packages d'exécution, le fait de placer rtl dylib dans le répertoire Products ne fait pas de différence. – msohn

+0

Si vous activez les packages d'exécution, puis n'utilisez aucun, le code ne sera pas lié à bpl160.dylib et ne tombera pas en panne. Lorsque vous liez statiquement, il compile dans l'équivalent statique de bpl160.dylib, ce qui déclenche le problème lorsque la bibliothèque est chargée. Vous pouvez obtenir une meilleure trace de pile en liant la bibliothèque de test en utilisant -lazy-lLibTest, ce qui provoque le problème au premier appel de la fonction exportée (c'est ainsi que j'ai suivi le problème). La raison de l'utilisation de paquets partagés est une habitude de problème d'exécution similaire à ce sous Windows. – Petesh

Questions connexes