cython生成dll踩坑记(一)—基础篇
2023-10-14
最近研究了一下cython,花了3天时间才写出了一点成果来(太菜了~~~)。关于cython的教程还是比较少的,大部分还是得自己摸索。(指修完一个bug又出现两个bug)。不过也确实感觉收获了许多。
- 坑点一,pyx并不能直接导出函数
pyx的本质是一个动态链接库,所以,我猜想能不能直接loadlibrary这个动态链接库。于是我写了一个简单的代码测试一下。
cdef public func1(): |
然后python setup.py build_ext生成pyd文件,拿pe工具一查,这导出表压根就没有func1函数…..
所以还是得老老实实的,先生成c代码,再生成dll。
- 坑点二,初始化写在了
DLL_PROCESS_ATTACH与DLL_PROCESS_DETACH里
一开始,我是这样的
|
结果发现在自己的电脑里总报错,后来,我选择手动初始化,手动释放,就没报错了
|
- 坑点三,
Py_Init_...()函数不管用
本来开始时,我的代码是
|
结果发现一直报指针访问不能为nullptr。
后来改成下面这样就好了。
PyImport_AppendInittab("test", PyInit_test); |
小提示: cython3.x版本用Py_Init_...()用这个过不了编译
- 坑点四,
__PYX_EXTERN_C不能加_declspec(dllexport)
看了cython生成的头文件,发现每个导出函数都有__PYX_EXTERN_C,于是添了个_declspec(dllexport)
结果发现无效
只能老老实实写函数去包装了
- 坑点五,无返回值时,返回值位PyObject问题
在编写cython函数时,无返回值的函数最好加上void而不是不写。
|
|
- 坑点六,字符串问题
c语言的wchar_t能直接当作cython的str类型来用。
c语言的char *能直接当作cython的bytes类型来用。
但是cython的str类型不能在c++文件里直接使用,要用Py_UNICODE。(bytes还没测试过)
其中Py_UNICODE是wchar_t的别名
typedef wchar_t Py_UNICODE |
而Py_UNICODE在python.h头文件和cython里均有定义
所以本人就直接在cython和c++文件统一用Py_UNICODE了(懒得思考类型转换问题)
举个例子
|
// dllmain.cpp |
生成dll后调用py_test1,传参wchar_t,就能在控制台打印出字符串了。
注意: char* 在cython中的类型是bytes,而且还需要考虑末尾填'\0'。 |
大体上我编译时遇到的问题就这些了。
基础篇就这些内容了,下一次就谈谈dll生成后的打包方式与变量共享问题吧
- 最后给个小提示,在开发时,把多用try把代码包起来,然后在except中print错误信息,能极大提高找bug效率