Динамическое связывание расширения Python (.pyd) с другим расширением - PullRequest
4 голосов
/ 17 июля 2010

Модули расширения Python - это просто динамические библиотеки, поэтому я предполагаю, что можно динамически связать расширение Python с другим.Проблема в Windows Python Расширения имеют расширение .pyd вместо .dll, поэтому я не могу получить distutils для ссылки на них при запуске сценария установки.(Я не думаю, что это проблема в UNIX, потому что расширения Python используют расширение .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])

Пока это не работает.Это вообще возможно?Я предполагаю, что это так, но я не смог ничего найти в Интернете.Я использую MinGW в Windows, но мне бы хотелось, чтобы это работало с другими 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 s в foo, которые, казалось, были переопределены в bar. Мне нужно, чтобы PyTypeObject s в обоих модулях относились к одному и тому же определению.).

Edit 2: Итак, я выделил проблему.Символы функций экспортировались корректно после того, как я собрал и связал их с библиотеками импорта, но PyTypeObject были повторно объявлены.Предположим, что было 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_Type как в foo, так и bar, и он ссылался на одно и то же определение Foo_Type.Проблема в том, что это не сработает в системах, отличных от Windows.Я предполагаю, что если я просто возьму __declspec s, он будет работать нормально на других системах.

Ответы [ 2 ]

1 голос
/ 17 июля 2010

Если вы используете обычные Python механизмы импорта , тогда нет необходимости связываться с другим расширением. Если вы вызываете функции из другого расширения, предположительно потому, что вы завладели заголовочным файлом, то вам нужно сгенерировать lib импорта из DLL, прежде чем вы сможете ссылаться на нее.

0 голосов
/ 20 октября 2017
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
    ]
);

от: http://pyd.readthedocs.io/en/latest/distutils.html

...