Связывание модулей расширения python

#python #c #pybind11

#python #c #pybind11

Вопрос:

У меня есть два модуля расширения, образно названные foo и bar . bar состоит из функции C и простой оболочки вокруг нее

 #include <pybind11/pybind11.h>

int add_numbers(int a, int b)
{
    return a   b;
}

int bar_add_numbers(int  a, int b)
{
    return add_numbers(a, b);
}

PYBIND11_MODULE(_bar, m)
{
    m.def("add_numbers", amp;bar_add_numbers);
}
  

foo имеет идентичную оболочку, но без определения.

 #include <pybind11/pybind11.h>

int add_numbers(int,  int);

int foo_add_numbers(int a, int  b)
{
    return add_numbers(a,  b);
}

PYBIND11_MODULE(_foo, m)
{
    m.def("add_numbers", amp;foo_add_numbers);
}
  

После сборки их с помощью setuptools

 import os
from setuptools import setup, Extension
import pybind11

os.environ['CC'] = 'clang  '
os.environ['CXX'] = 'clang  '

libbar = Extension('foo._bar',
    sources = ['bar.cpp'],
    extra_compile_args=['-std=c  14'],
    include_dirs = [pybind11.get_include()]
)

libfoo = Extension('foo._foo',
    sources = ['foo.cpp'],
    extra_compile_args=['-std=c  14'],
    include_dirs = [pybind11.get_include()]
)


setup(name='foo',
    version='1.0.0',
    ext_modules = [libbar, libfoo]
)
  

мое ожидание (надежда) заключалось в том, что, если foo._foo оно было импортировано после foo._bar , тогда add_numbers оно должно быть правильно разрешено из любой оболочки. Похоже, это имеет место в OSX.

 >>> from foo import _bar
>>> from foo import _foo
>>>  _foo.add_numbers(40, 2)
42
  

Однако в окне ubuntu это не удается undefined symbol: _Z11add_numbersii . И как раз тогда, когда я подумал, что у меня могут быть почти рабочие знания о динамическом связывании.

Что мне нужно сделать по-другому в Linux (или, более конкретно, в дистрибутивах на основе debian), чтобы это заработало?

РЕДАКТИРОВАТЬ: вывод из nm двух файлов .so

 $ nm _bar.cpython-37m-x86_64-linux-gnu.so | grep "add_numbers"
0000000000004a50 T _Z11add_numbersii
0000000000004a60 T _Z15bar_add_numbersii
  

и

 $ nm _foo.cpython-37m-x86_64-linux-gnu.so | grep "add_numbers"
                 U _Z11add_numbersii
00000000000048c0 T _Z15foo_add_numbersii
  

И fwiw флаги компилятора

 clang   -pthread -shared -Wl,-O1 -Wl,-Bsymbolic-functions -Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-Bsymbolic-functions -Wl,-z,relro -g -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2
  

Комментарии:

1. Если у вас одно и то же имя (например, «add_numbers») в двух разных, но одновременных библиотеках, какую из них можно использовать?

2. add_numbers определяется только один раз.

3. Чтобы было немного понятнее, символ _Z11add_numbersii определяется (в данном случае) в модуле расширения _bar.cpython-37m-x86_64-linux-gnu.so . Я ожидал, что как только интерпретатор python загрузит этот модуль, функция может быть вызвана из другого модуля расширения. Похоже, это работает на OSX, но не на компьютере Ubuntu, и я немного не понимаю, в чем может быть разница.

4. Можете ли вы отредактировать свой вопрос с nm выводом для этой функции в обоих .so файлах? Я подозреваю, что это может быть из-за видимости по умолчанию.

5. Выполнено. Я подумал то же самое, но подумал, что видимость по умолчанию общедоступна (хотя я здесь не в своей тарелке).