我在 Cython 中包装了一个小型 C 库,并且可以从 Python 中成功调用它。这是一个简化的示例,表示目前的情况:
# wrapper_module.pyx
cdef extern from "my_c_library.h":
void function1()
int function2(int param1, char *param2)
class MyWrapperClass():
def __init__(self):
pass
def do_func1(self):
function1()
def do_func2(self, p1, p2):
function2(p1, p2)
这一切都很好。我现在的目标是在单独的进程中创建和使用 MyWrapperClass
的实例,如下所示:
# my_script.py
import multiprocessing as mp
from wrapper_module import MyWrapperClass
class MyProcess(mp.Process):
def __init__(self):
super().__init__()
def run(self):
self.mwc = MyWrapperClass()
self.mwc.do_func1()
# ... do more
if __name__ == '__main__':
proc = MyProcess()
proc.start()
当我运行 my_script.py 时,出现以下错误:
The process has forked and you cannot use this CoreFoundation functionality safely. You MUST exec(). Break on THE_PROCESS_HAS_FORKED_AND_YOU_CANNOT_USE_THIS_COREFOUNDATION_FUNCTIONALITY___YOU_MUST_EXEC() to debug.
我想我大致理解为什么它不允许将此 cython 模块 fork 到不同的进程中(由于底层 C 库使用的资源)。但一般来说,当我过去遇到这类问题时,无论是在纯 Python 中还是使用 ctypes 并调用 DLL,我都可以通过将所有关键代码放在 的
,导致它只在新派生的进程中初始化。run
方法中来解决它MyProcess
但是,在这个 Cython 案例中,我不知道如何仅在 fork 进程中包含 cdef extern
代码,以避免此错误。有什么建议吗?
(我在 macOS 10.12 上运行 python 3.6.2)
最佳答案
cdef extern
中的代码只是对外部c函数的声明(我们只考虑c),这些声明被放入生成的c文件中(几乎)没有任何变化,与初始化。
我也做了一个相当简单的测试(py3.6 windows):
lib.c:
int add(int a, int b)
{
return a + b ;
}
mylib.pyx:
cdef extern from "lib.c":
int _add "add"(int a, int b)
cdef class WrapperClass:
def add(self, a, b):
return _add(a, b)
test_lib.py:
from mylib import WrapperClass
import multiprocessing as mp
class MyProcess(mp.Process):
def __init__(self):
super().__init__()
def run(self):
self.mwc = WrapperClass()
print(self.mwc.add(1, 2))
if __name__ == "__main__":
proc = MyProcess()
proc.start()
运行 python test_lib.py
没有任何问题。也许我的 C 代码太简单了,但我不知道你的 C 函数到底做了什么,myabe 这才是真正的问题。
关于python - 如何通过多处理在单独的 Python 进程中使用用 Cython 包装的外部 C 库?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46456499/