2010-07-17 5 views
3

Les modules d'extension Python ne sont que des bibliothèques dynamiques. Je suppose donc qu'il est possible de lier dynamiquement une extension Python à une autre. Le problème est sur Windows Python extensions sont donnés l'extension .pyd au lieu de .dll, donc je ne peux pas obtenir distutils à lier à eux lorsque je cours le script d'installation. (Je ne pense pas que ce soit un problème sous UNIX, car les extensions Python utilisent l'extension de fichier .so.)Lier dynamiquement une extension Python (.pyd) à une autre extension

Supposons que j'ai une extension bar.pyd qui doit créer un lien vers foo.pyd. Au fond, ce que je faisais dans le script de configuration a été:

from distutils.core import setup, Extension 

foo = Extension("foo", sources=["foo.c"]) 
bar = Extension("bar", libraries=["foo"], sources=["bar.c"]) 
setup(ext_modules=[foo, bar]) 

Jusqu'à présent, cela ne fonctionne pas. Est-ce seulement possible? Je suppose que c'est le cas, mais je n'ai pas été en mesure de trouver quelque chose en ligne. J'utilise MinGW sous Windows, mais j'aimerais que cela fonctionne avec MSVC++ différent et sur d'autres systèmes.

Edit: Auparavant, je résolu ce problème en passant le fichier objet (foo.o) créé lorsque foo a été compilé à l'option extra_objects dans l'extension (cela ne fonctionnera que si je définissais des prototypes de tous foo symboles bar) :

bar = Extension("bar", sources=["bar.c"], extra_objects=["build/.../foo.o"] 

Cela ne semble pas être la bonne solution, mais cela a fonctionné. Je ne comprends pas bien le lien dynamique, alors c'est peut-être la bonne façon de le faire. C'est très mal, cependant.

Ensuite, j'ai essayé passer quelques arguments explicites à gcc pour le compiler une bibliothèque d'importation:

foo = Extension("foo", sources=["foo.c"], extra_compile_args=["-Wl,--out-implib,foo.lib,--export-all-symbols"]) 

Et puis je lié bar à la nouvelle bibliothèque d'importation:

bar = Extension("bar", libraries=["foo"], sources=["bar.c"]) 

Cette compilation sans plainte, mais il y avait quelques problèmes avec certains des symboles (en particulier, j'ai eu quelques PyTypeObject s dans foo s qui ont semblé être redéfini en bar J'ai besoin de PyTypeObject s dans les deux modules se réfèrent à la même définition.).

Édition 2: Donc, j'ai isolé le problème. Les symboles de fonction exportaient correctement après avoir construit et lié les bibliothèques d'importation, mais les PyTypeObject étaient redéclarés. Supposons qu'il y ait eu un PyTypeOject Foo_Type dans foo. Je déclarais dans foo.h, qui a été inclus dans les deux foo.c et bar.c:

PyTypeObject Foo_Type; 

J'ai pris que dehors, et mettre ce en haut de foo.c:

PyTypeObject __declspec(dllexport) Foo_Type; 

et ce en haut de bar.c :

PyTypeObject __declspec(dllimport) Foo_Type; 

Cela a résolu le problème. Je pourrais alors utiliser Foo_Type à la fois foo et bar et il se référait à la même définition de Foo_Type. Le problème est, cela ne va pas fonctionner sur les systèmes non-Windows. Je suppose que si je prends juste le __declspec, il fonctionnera bien sur d'autres systèmes.

Répondre

1

Si vous utilisez le Python normal import mechanisms, il n'est pas nécessaire de lier l'autre extension. Si vous appelez des fonctions au sein de l'autre extension, probablement parce que vous avez pris le contrôle du fichier d'en-tête, vous devrez générer une bibliothèque d'importation à partir de la DLL avant de pouvoir la lier.

+0

Ces deux modules d'extension font partie de mon projet, je voudrais relier entre eux au lieu d'utiliser les mécanismes d'importation Python. Je suis assez nouveau à ce sujet, donc, je ne suis pas tout à fait sûr de savoir comment générer la bibliothèque d'importation. Pouvez-vous nous éclairer à ce sujet? –

0
from distutils.core import Extension as cExtension 
from pyd.support import setup, Extension 

module1 = Extension("x", sources = ['xclass.c']) 
module2 = Extension("y", sources = ['hello.d'], build_deimos=True) 

setup(
    name = "x", 
    version = '1.0', 
    description = "eat a taco", 
    ext_modules = [ 
     module1, 
     module2 
    ] 
); 

de: http://pyd.readthedocs.io/en/latest/distutils.html

+0

Cela n'a rien à voir avec le langage de programmation D. –

Questions connexes