使用 ctypes 创建一个 python 模块

Posted

技术标签:

【中文标题】使用 ctypes 创建一个 python 模块【英文标题】:creating a python module using ctypes 【发布时间】:2021-03-29 01:34:05 【问题描述】:

我有一个只有两个函数的 C 库:char *foo_decode(const char*)const char *foo_version()

我现在想创建一个允许调用这两个函数的 python 模块。

C 库编译成foo.so

这是我的python模块文件:

$ cat foo.py
import ctypes as ct

_lib = ct.cdll.LoadLibrary("./foo.so")
_lib.foo_decode.argtypes = [ct.c_char_p]
_lib.foo_decode.restype = ct.c_char_p
_lib.foo_version.argtypes = []
_lib.foo_version.restype = ct.c_char_p

def decode(fooText):
    return _lib.foo_decode(fooText.encode('utf8')).decode('utf-8')
    
def version():
    return _lib.foo_version().decode('utf-8')

我关注了this tutorial。

当我启动一个 python3 解释器并手动执行它时。一切正常。 我可以调用这些函数并得到预期的结果。

但是当我导入我的模块文件 (import foo) 时,我收到错误 ImportError: dynamic module does not define module export function (PyInit_foo)

发生了什么,我应该怎么做才能解决这个问题?

我的目标是生成一个可通过 pip install 下载的包。我在正确的轨道上吗?我不想要***,因为代码很小并且没有依赖关系。因此我应该快速编译并且应该非常便携。

【问题讨论】:

顺便说一句,global 语句完全没有必要,您应该删除它们。 @juanpa.arrivillaga 我删除了global _lib。谢谢 在这种情况下,动态模块名称以下划线开头:_foo.so 【参考方案1】:

您有一个共享库foo.so 和一个模块foo.py。当 Python 执行 import foo 时,它只加载其中一个;在你的情况下是foo.so;但foo.so 不是 Python 模块,因此会出现错误。

将您的 foo.py 重命名为 foo_wrapper.py 之类的不同名称,然后尝试 import foo_wrapper

【讨论】:

这行得通。非常感谢。生成 .so 文件时我有点快。通常,.so 文件被命名为libfoo.so。这样可以避免混淆。我更喜欢调用模块foo 当然,所有名称都由您决定。只是不要将 Python 的导入与相同的名称混淆。 :-)

以上是关于使用 ctypes 创建一个 python 模块的主要内容,如果未能解决你的问题,请参考以下文章

使用 Python 的 ctypes 调用涉及自定义类型的函数

python--ctypes模块:调用C函数

[转]python使用ctypes模块调用windowsapi获取系统版本

使用ctypes和python并调用libc accept时的EFAULT

ctypes给扩展模块中的函数传递数组和结构体

聊聊Python ctypes 模块(转载)