我有一个Cython项目,包含以下模块:
CythonModule.pyx:
cdef int CPyFuncSwo():
print("Do some stuff in cython")
return 0
def PyFuncSwo()
CPyFuncSwo()
print("Do some stuff but in pure python only")
CythonModule.pxd:
cdef int CPyFuncSwo()
Setup.py:
from distutils.core import setup, Extension
from Cython.Build import cythonize
ext_modules = [
Extension(
"CythonModule",
sources=["CythonModule.pyx",],
),
]
setup(
name="CythonModule",
ext_modules=cythonize(ext_modules),
compiler_directives={'language_level': 3, "unraisable_tracebacks": True}
)
run.py:
import os
import sys
from CythonModule import PyFuncSwo
sys.path.insert(0, os.path.abspath("."))
if __name__ == '__main__':
PyFuncSwo()
这工作得很好,当我运行python setup.py build_ext --inplace && python run.py
时,代码编译并运行,同时也给了我一个新的CythonModule.cp39-win_amd64.pyd
文件。现在我需要在纯C/C++代码中从.pyd模块调用PyFuncSwo()
。在网上冲浪时,我遇到了下面的例子:
RunCythonInC.c:
#include <windows.h>
#include <stdio.h>
typedef (add_proc)(int a, int b);
int main(){
add_proc *add;
HANDLE h_dll;
int a = 1, b = 2, c;
h_dll = LoadLibrary("CythonModule.cp39-win_amd64.pyd");
if(h_dll)
{
add = GetProcAddress(h_dll, "PyFuncSwo");
if(add)
{
c = add(a, b); /*Explicit Call*/
}
else
{
printf("PyFuncSwo not found in CythonModule.cp39-win_amd64.pyd");
}
FreeLibrary(h_dll);
}
else
{
printf("Unable to load CythonModule.cp39-win_amd64.pyd");
exit(-1);
}
return 0;
}
使用gcc将此代码编译为gcc -g RunCythonInC.c -o RunCythonInC.exe
编译时会出现以下警告,但当我运行RunCythonInC.exe时,总是得到PyFuncSwo not found in CythonModule.cp39-win_amd64.pyd
。
我还将GetProcAddress(h_dll, "PyFuncSwo")
更改为GetProcAddress(h_dll, "CPyFuncSwo")
,但仍然得到相同的错误。我尝试的其他事情是使用_ as GetProcAddress(h_dll, "_PyFuncSwo")
调用cython函数,但仍然得到相同的结果。有人能告诉我,如何在纯C代码中从.pyd模块调用cython函数?
1条答案
按热度按时间hc2pp10m1#
您的直接问题是符号可见性。函数需要是
cdef public
,可能是need manually exporting on Windows。然而
你正在尝试做的是错误的,不太可能工作。
Cython不创建独立的C函数。相反,它生成Python模块。Cython函数有两个重要的先决条件:
如果不满足这些先决条件,函数很可能会以意想不到和令人困惑的方式崩溃。
从C调用Cython函数的正确方法在Cython文档中介绍,不涉及
GetProcAddress
。