本文由腾讯云+社区自动同步,原文地址
https://stackoverflow.club/104/
本篇内容来自原创小册子《python高阶教程》
背景
某些情况下,我们需要python与其他编程语言,如c/c++联合运行,以获得额外的性能或者功能。比如,将
经常调用的业务逻辑用c重写一遍,提高效率;或者重复利用已经开发好的dll库,缩短开发周期。
两种调用c/c++库的方式
-
__stdcall方式
在python中通过
dll = ctypes.WinDLL("TestDll.dll")
调用
-
__cdecl方式
在python中通过
dll = ctypes.cdll.LoadLibrary("TestDll.dll")
调用
具体使用了哪种方式需要看源码,如果不知道源码,可以两种方式都试试,错误的调用方式会
出现以下ValueError.
ValueError: Procedure called with not enough arguments (8 bytes missing) or wrong calling convention
查看dll中的函数名称
实际上,编译器会修改函数的名称。虽然可以通过
.def
文件来禁止编译器做修改,但是尚未发现在MinGW上如果操作。在本文中使用
Dependency Walker(depends)
软件读取dll中的函数列表,获取函数名称。
下载地址
简单Demo
1.TestDll.h文件
#ifdef __cplusplus
extern "C"{
#endif
int __stdcall __declspec(dllexport) MyAdd(int nA, int nB);
#ifdef __cplusplus
#endif
2.TestDll.cpp文件
#include "TestDll.h"
#ifdef __cplusplus
extern "C"{
#endif
int __stdcall __declspec(dllexport) MyAdd(int nA, int nB)
return nA + nB;
#ifdef __cplusplus
#endif
3.TestDll.bat编译脚本
gcc TestDll.cpp -shared -o TestDll.dll
4.TestDll.py调用
import ctypes
# 导出函数是__stdcall声明的使用
dll = ctypes.WinDLL("TestDll.dll")
# 导出函数是__cdecl声明的使用
#dll = ctypes.cdll.LoadLibrary("TestDll.dll")
summmm = getattr(dll, 'MyAdd@8')
ret = summmm(2, 4)
print(ret)
运行后会看到python脚本输出了正确结果。
TODO
-
ctypes中的c与python对象映射表
-
指针作为参数