В этих документах есть хороший пример того, как скомпилировать некоторый внешний код C / C ++ и загрузить его, используя ctypes . Это прекрасно работает с ручной компиляцией (где я контролирую имена моей библиотеки, которая позже загружается).
Теперь, как подготовить некоторый код для использования в Scipy с полным включением в систему сборки Scipy? Более общий GitHub-выпуск не предоставляет информацию, которую я ищу для (и, к сожалению, не так много действий).
Кроме того: меня больше интересует использование ctypes (никакого реального использования в scipy? Несмотря на предоставленные явные инструменты numpy?), А не cython, который используется во всех других оболочках (я не вижу веских оснований для cython, за исключением его общего использования: моя библиотека будет загружаться / вызываться только один раз, и это медленно по сравнению с потенциальными накладными расходами на вызовы).
Давайте предположим, что я добавил каталог вроде:
scipy/optimize/_mylib/README
...
scipy/optimize/_mylib/src
scipy/optimize/_mylib/src/a.cpp
...
... bunch of cpp/h files
Давайте коснемся scipy/optimize/setup.py
:
from __future__ import division, print_function, absolute_import
from os.path import join
from scipy._build_utils import numpy_nodepr_api
def configuration(parent_package='',top_path=None):
from numpy.distutils.misc_util import Configuration
from numpy.distutils.system_info import get_info
config = Configuration('optimize',parent_package, top_path)
# MODIFICATION START
# OTHER EXTENSIONS OMITTED
# INSPIRED BY scipy.spatial: ckdtree/src & setup.py
mylib_src = ['a.cpp', 'b.cpp']
mylib_src = [join('_mylib', 'src', x) for x in mylib_src]
mylib_headers = ['a.h', 'b.h']
mylib_headers = [join('_mylib', 'src', x) for x in mylib_headers]
mylib_dep = mylib_headers + mylib_src
config.add_extension('_mylib',
sources=mylib_src,
depends=mylib_dep,
include_dirs=[join('_mylib', 'src')])
# MODIFICATION END
return config
if __name__ == '__main__':
from numpy.distutils.core import setup
setup(**configuration(top_path='').todict())
Теперь это работает в отношении:
# in scipy base-dir
python3 setup.py build_ext --inplace
, который производит (в пределах scipy.optimize
):
_mylib.cpython-35m-x86_64-linux-gnu.so
и может быть загружен в интерпретатор (начиная с dir scipy.optimize
)
import numpy.ctypeslib as ctl
lib = ctl.load_library('_mylib.cpython-35m-x86_64-linux-gnu.so', '.')
lib
# <CDLL '/home......._mylib.cpython-35m-x86_64-linux-gnu.so', handle X at X
Теперь вопрос
Если я хочу добавить новый файл:
scipy/optimize/new_alg.py
Независимо от того, что я пытаюсь, я не могу загрузить это. E.g.:
# this is scipy/optimize/new_alg.py
import numpy.ctypeslib as ctl
mylib = ctl.load_library('_mylib', '.')
mylib = ctl.load_library('_mylib', '.optimize')
# ...
Второй аргумент, вероятно, должен быть полным путем (в отличие от частичных или подстановочных знаков). Все мои попытки потерпели неудачу с общей ошибкой :
OSError: no file with expexted extension
Что мне здесь делать? (цель: быть готовым стать настоящим дополнением к scipy: несколько платформ).
Обречен ли сам подход? С наивной точки зрения это многообещающе: ожидаемые недостатки ctypes для меня не важны, и это часть стандарта. Кроме того, он получил специальную поддержку в numpy, и я контролирую C / C ++ - часть, так что я могу предоставить упрощенную однофункциональную оболочку для вызова. Почему это не используется в других частях scipy?