[英]Python extension with multiple modules
我正在為我編寫的獨立 C 庫構建 Python 綁定。 該庫的文件布局如下:
<project root>
|
`- cpython
| |
| `- module1_mod.c
| `- module2_mod.c
| `- module3_mod.c
|
`- include
| |
| `- module1.h
| `- module2.h
| `- module3.h
|
`- src
| |
| `- module1.c
| `- module2.c
| `- module3.c
|
`- setup.py
我想獲得一個 Python package 以便我可以在my_package.module1
、 my_package.module2
等命名空間中導入模塊。
到目前為止,這是我的setup.py
:
from os import path
from setuptools import Extension, setup
ROOT_DIR = path.dirname(path.realpath(__file__))
MOD_DIR = path.join(ROOT_DIR, 'cpython')
SRC_DIR = path.join(ROOT_DIR, 'src')
INCL_DIR = path.join(ROOT_DIR, 'include')
EXT_DIR = path.join(ROOT_DIR, 'ext')
ext_libs = [
path.join(EXT_DIR, 'ext_lib1', 'lib.c'),
# [...]
]
setup(
name="my_package",
version="1.0a1",
ext_modules=[
Extension(
"my_package.module1",
[
path.join(SRC_DIR, 'module1.c',
path.join(MOD_DIR, 'module1_mod.c',
] + ext_libs,
include_dirs=[INCL_DIR],
libraries=['uuid', 'pthread'],
),
],
)
導入mypackage.module1
有效,但問題是module2
和module3
也需要外部庫(並非所有模塊都需要外部庫),我假設如果我在其他模塊中包含相同的外部庫,我會得到很多膨脹。
我查看了 Github 中的示例設置,但沒有找到解決此問題的示例。
什么是組織我的構建的好方法?
編輯:這實際上是一個更嚴重的問題,因為我在module1
中有module2
module2
的 object 需要在 module1 中定義的module1
類型。 如果我創建單獨的二進制文件而不包括每個依賴項的所有源,則符號在鏈接時將不可用,從而增加了跟蹤哪個模塊所需內容的冗余和復雜性。
在深入研究 Python 錯誤報告和幾乎沒有文檔記錄的功能后,我找到了一個答案,它解決了多個外部依賴項和內部交叉鏈接。
解決方案是創建一個整體“模塊”,其中定義了所有模塊,然后在 package 初始化文件中使用幾行 Python 代碼公開它們。
為此,我將模塊源文件更改為 header 文件,維護他們的大部分方法 static 並且只公開PyTypeObject
結構和我的 object 類型的結構,因此它們可以用於其他模塊。
然后我移動了PyMODINIT_FUNC
函數,它定義了“包”模塊( py_mypackage.c
)中的所有模塊,該模塊還定義了一個空模塊。 “包”模塊定義為_my_package
。
最后,我在__init__.py
腳本中添加了一些內部機制,該腳本從.so 文件中提取模塊符號並將它們公開為 package 的模塊。 這記錄在Python 文檔中:
import importlib.util
import sys
import _my_package
pkg_path = _my_package.__file__
def _load_module(mod_name, path):
spec = importlib.util.spec_from_file_location(mod_name, path)
module = importlib.util.module_from_spec(spec)
sys.modules[mod_name] = module
spec.loader.exec_module(module)
return module
for mod_name in ('module1', 'module2', 'module3'):
locals()[mod_name] = _load_module(mod_name, pkg_path)
因此,新的布局是:
<project root>
|
`- cpython
| |
| `- my_package
| |
| `- __init__.py
|
| `- py_module1.h
| `- py_module2.h
| `- py_module3.h
| `- py_mypackage.c
|
`- include
| |
| `- module1.h
| `- module2.h
| `- module3.h
|
`- src
| |
| `- module1.c
| `- module2.c
| `- module3.c
|
`- setup.py
和setup.py
:
setup(
name="my_package",
version="1.0a1",
package_dir={'my_package': path.join(CPYTHON_DIR, 'my_package')},
packages=['my_package'],
ext_modules=[
Extension(
"_my_package",
"<all .c files in cpython folder + ext library sources>",
libraries=[...],
),
],
)
出於好奇,完整的代碼位於https://notabug.org/scossu/lsup_rdf/src/e08da1a83647454e98fdb72f7174ee99f9b8297c/cpython (固定在當前提交處)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.