Python拡張モジュールは単なるダイナミックライブラリなので、Python拡張を別の拡張に動的にリンクできると思います。問題はWindowsにあります。Python拡張機能にはの.pyd
代わりに拡張機能が与えられている.dll
ため、セットアップスクリプトを実行するときにdistutilsをそれらにリンクさせることができません。(Python拡張機能はファイル拡張子を使用するため、これはUNIXでは問題ではないと思い.so
ます。)
bar.pyd
にリンクする必要のある拡張子があると仮定しfoo.pyd
ます。基本的に、セットアップスクリプトで行ったことは次のとおりです。
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])
これまでのところ、これは機能していません。これも可能ですか?そうだと思いますが、オンラインで何も見つかりませんでした。私はWindowsでMinGWを使用していますが、これを別のMSVC++や他のシステムでも動作させたいと思います。
編集:以前は、コンパイル時に作成されたオブジェクトファイル(foo.o
)を拡張機能のオプションに渡すことでこの問題を解決しました(これは、ですべてのシンボルのプロトタイプを定義した場合にのみ機能します):foo
extra_objects
foo
bar
bar = Extension("bar", sources=["bar.c"], extra_objects=["build/.../foo.o"]
これは正しい解決策ではなかったようですが、うまくいきました。私はダイナミックリンクをよく理解していないので、これはそれを行う正しい方法かもしれません。しかし、それは非常に間違っていると感じます。
次に、いくつかの明示的な引数をgccに渡して、インポートライブラリをコンパイルするようにしました。
foo = Extension("foo", sources=["foo.c"], extra_compile_args=["-Wl,--out-implib,foo.lib,--export-all-symbols"])
bar
次に、新しいインポートライブラリにリンクしました。
bar = Extension("bar", libraries=["foo"], sources=["bar.c"])
これは文句なしにコンパイルされましたが、いくつかのシンボルにいくつかの問題がありました(具体的には、で再定義されたように見えるいくつかPyTypeObject
のfoo
グローバルがありましたbar
。両方のモジュールのが同じ定義を参照する必要がありPyTypeObject
ます)。
編集2:それで、私は問題を選び出しました。インポートライブラリをビルドしてリンクした後、関数シンボルは正しくエクスポートされていましたが、PyTypeObject
sが再宣言されていました。にがあったと仮定PyTypeOject Foo_Type
しfoo
ます。私はそれをで宣言しました、それはとの両方にfoo.h
含まれていました:foo.c
bar.c
PyTypeObject Foo_Type;
私はそれを取り出して、これを上部近くに置きましたfoo.c
:
PyTypeObject __declspec(dllexport) Foo_Type;
そしてこれは上部近くにありbar.c
ます:
PyTypeObject __declspec(dllimport) Foo_Type;
これで問題は解決しました。次に、両方foo
でFoo_Typeを使用でき、Foo_Typebar
の同じ定義を参照しました。問題は、これがWindows以外のシステムでは機能しないことです。__declspec
sを取り出すだけで、他のシステムでも問題なく動作すると思います。