ctypes 是 Python 的外部函数库。它提供了与 C 兼容的数据类型,并允许调用 DLL 或共享库中的函数。可使用该模块以纯 Python 形式对这些库进行封装。
Hello World
- 编写C文件
- 编译C文件
- 编写Python文件、测试
1. 编写C文件
1 |
|
2. 编译C文件
不同平台生成不同格式的动态库,windows下为dll,linux下为so
gcc -fPIC -shared hello_module.c -o hello_module.dylib
3. 编写Python文件
1 |
|
类型映射关系
ctypes | C 类型 | Python类型 |
---|---|---|
c_bool | _Bool | bool (1) |
c_char | char | 单字符字节对象 |
c_wchar | wchar_t | 单字符字符串 |
c_byte | char | int |
c_ubyte | unsigned char | int |
c_short | short | int |
c_ushort | unsigned short | int |
c_int | int | int |
c_uint | unsigned int | int |
c_long | long | int |
c_ulong | unsigned long | int |
c_longlong | __int64 或 long long | int |
c_ulonglong | unsigned __int64 或 unsigned long long | int |
c_size_t | size_t | int |
c_ssize_t | ssize_t 或 Py_ssize_t | int |
c_float | float | float |
c_double | double | float |
c_longdouble | long double | float |
c_char_p | char * (NUL terminated) | 字节串对象或 None |
c_wchar_p | wchar_t * (NUL terminated) | 字符串或 None |
c_void_p | void * | int 或 None |
回调函数
1 | ############# |
1 |
|
参考:http://blog.sina.com.cn/s/blog_6e22d8fb0102y462.html
线程状态和GIL
Python解释器不是完全线程安全的。为了支持多线程Python程序,有一个全局锁,称为global interpreter lock或GIL,它必须由当前线程持有才能安全访问Python对象。没有锁,即使最简单的操作也可能导致多线程程序中的问题:例如,当两个线程同时增加同一对象的引用计数时,引用计数可能最终只增加一次而不是两次。
释放GIL
1 | Py_BEGIN_ALLOW_THREADS |
非Python创建的线程
当使用专用的Python API(例如threading模块)创建线程时,线程状态会自动关联到它们,因此上面显示的代码是正确的。但是,当从C创建线程时(例如由具有自己的线程管理的第三方库),它们不持有GIL,也没有线程状态结构。
如果你需要从这些线程调用Python代码(通常这将是上述第三方库提供的回调API的一部分),你必须首先通过创建线程状态数据结构来注册这些线程和解释器,然后获取GIL,最后存储他们的线程状态指针,然后才能开始使用Python / C API。当你完成后,你应该重置线程状态指针,释放GIL,最后释放线程状态数据结构。
1 | PyGILState_STATE gstate; |
释放GIL和非python创建的线程中调用python函数都没有测试成功…