Python调用C/C++动态链接库的方法详解


Posted in Python onJuly 22, 2014

本文以实例讲解了Python调用C/C++ DLL动态链接库的方法,具体示例如下:

示例一:

首先,在创建一个DLL工程(本例创建环境为VS 2005),头文件:

//hello.h
#ifdef EXPORT_HELLO_DLL
#define HELLO_API __declspec(dllexport)
#else
#define HELLO_API __declspec(dllimport)
#endif
extern "C"
{
 HELLO_API int IntAdd(int , int);
}

CPP文件:

//hello.cpp
#define EXPORT_HELLO_DLL
#include "hello.h"
HELLO_API int IntAdd(int a, int b)
{
 return a + b;
}

这里有两个注意点:

(1)弄清楚编译的时候函数的调用约定采用的__cdecl还是__stdcall,因为根据DLL中函数调用约定方式,Python将使用相应的函数加载DLL。

(2)如果采用C++的工程,那么导出的接口需要extern "C",这样python中才能识别导出的函数。

我的工程中采用__cdecl函数调用约定方式进行编译链接产生hello.dll,然后Python中采用ctypes库对hello.dll进行加载和函数调用:

from ctypes import *
dll = cdll.LoadLibrary('hello.dll');
ret = dll.IntAdd(2, 4);
print ret;

至此,第一个小例子已经完成了,读者可以自己动手尝试一下运行效果。

示例二:

示例一只是一个"hello world"级别的程序,实际运用中更多的需要传递数据结构、字符串等,才能满足我们的需求。那么本示例将展示,如何传递数据结构参数,以及如何通过数据结构获取返回值。

首先编写DLL工程中的头文件:

//hello.h
#ifdef EXPORT_HELLO_DLL
#define HELLO_API __declspec(dllexport)
#else
#define HELLO_API __declspec(dllimport)
#endif

#define ARRAY_NUMBER 20
#define STR_LEN 20

struct StructTest
{
 int number;
 char* pChar;
 char str[STR_LEN];
 int iArray[ARRAY_NUMBER];
};

extern "C"
{
 //HELLO_API int IntAdd(int , int);
 HELLO_API char* GetStructInfo(struct StructTest* pStruct);
}

CPP文件如下:

//hello.cpp
#include <string.h>
#define EXPORT_HELLO_DLL
#include "hello.h"

HELLO_API char* GetStructInfo(struct StructTest* pStruct)
{
 for (int i = 0; i < ARRAY_NUMBER; i++)
 pStruct->iArray[i] = i;
 pStruct->pChar = "hello python!";
 strcpy (pStruct->str, "hello world!");
 pStruct->number = 100;
 return "just OK";
}

GetStructInfo这个函数通过传递一个StructTest类型的指针,然后对对象中的属性进行赋值,最后返回"just OK".

编写Python调用代码如下,首先在Python中继承Structure构造一个和C DLL中一致的数据结构StructTest,然后设置函数GetStructInfo的参数类型和返回值类型,最后创建一个StructTest对象,并将其转化为指针作为参数,调用函数GetStrcutInfo,最后通过输出数据结构的值来检查是否调用成功

from ctypes import *
ARRAY_NUMBER = 20;
STR_LEN = 20;
#define type
INTARRAY20 = c_int * ARRAY_NUMBER;
CHARARRAY20 = c_char * STR_LEN;
#define struct
class StructTest(Structure):
  _fields_ = [
    ("number", c_int),
    ("pChar", c_char_p),
    ("str", CHARARRAY20),
    ("iArray", INTARRAY20)
        ]
#load dll and get the function object
dll = cdll.LoadLibrary('hello.dll');
GetStructInfo = dll.GetStructInfo;
#set the return type
GetStructInfo.restype = c_char_p;
#set the argtypes
GetStructInfo.argtypes = [POINTER(StructTest)];
objectStruct = StructTest();
#invoke api GetStructInfo
retStr = GetStructInfo(byref(objectStruct));
#check result
print "number: ", objectStruct.number;
print "pChar: ", objectStruct.pChar;
print "str: ", objectStruct.str;
for i,val in enumerate(objectStruct.iArray):
  print 'Array[i]: ', val;
print retStr;

总结:

1. 用64位的Python去加载32位的DLL会出错
2. 以上只是些测试程序,在编写Python过程中尽可能的使用"try Except"来处理异常
3. 注意在Python与C DLL交互的时候字节对齐问题
4. ctypes库的功能还有待继续探索

Python 相关文章推荐
Python原始字符串(raw strings)用法实例
Oct 13 Python
python入门之语句(if语句、while语句、for语句)
Jan 19 Python
深入Python函数编程的一些特性
Apr 13 Python
使用python遍历指定城市的一周气温
Mar 31 Python
使用pycharm生成代码模板的实例
May 23 Python
python 读取.csv文件数据到数组(矩阵)的实例讲解
Jun 14 Python
Sanic框架蓝图用法实例分析
Jul 17 Python
使用TensorFlow对图像进行随机旋转的实现示例
Jan 20 Python
django正续或者倒序查库实例
May 19 Python
pycharm专业版远程登录服务器的详细教程
Sep 15 Python
Python监听键盘和鼠标事件的示例代码
Nov 18 Python
python图像处理 PIL Image操作实例
Apr 09 Python
使用python编写批量卸载手机中安装的android应用脚本
Jul 21 #Python
使用python编写脚本获取手机当前应用apk的信息
Jul 21 #Python
使用python编写android截屏脚本双击运行即可
Jul 21 #Python
python 示例分享---逻辑推理编程解决八皇后
Jul 20 #Python
python中from module import * 的一个坑
Jul 20 #Python
用python代码做configure文件
Jul 20 #Python
python中的内置函数getattr()介绍及示例
Jul 20 #Python
You might like
PHP 和 MySQL 开发的 8 个技巧
2007/01/02 PHP
木翼下载系统中说明的PHP安全配置方法
2007/06/16 PHP
解析web文件操作常见安全漏洞(目录、文件名检测漏洞)
2013/06/29 PHP
tp5(thinkPHP5框架)时间查询操作实例分析
2019/05/29 PHP
thinkphp5框架实现数据库读取的数据转换成json格式示例
2019/10/10 PHP
用于table内容排序
2006/07/21 Javascript
jQuery 入门讲解1
2009/04/15 Javascript
Javascript面向对象设计一 工厂模式
2011/12/20 Javascript
JS简单的图片放大缩小的两种方法
2013/11/11 Javascript
Jquery AJAX POST与GET之间的区别
2013/11/14 Javascript
JQUERY 设置SELECT选中项代码
2014/02/07 Javascript
原生javascript实现图片弹窗交互效果
2015/01/12 Javascript
jQuery实现本地预览上传图片功能
2016/01/08 Javascript
用js动态添加html元素,以及属性的简单实例
2016/07/19 Javascript
EasyUI 中combotree 默认不能选择父节点的实现方法
2016/11/07 Javascript
BootStrap 下拉菜单点击之后不会出现下拉菜单(下拉菜单不弹出)的解决方案
2016/12/14 Javascript
JavaScript如何判断input数据类型
2020/02/06 Javascript
JavaScript面试中常考的字符串操作方法大全(包含ES6)
2020/05/10 Javascript
Vue组件间数据传递的方式(3种)
2020/07/13 Javascript
Vue 电商后台管理项目阶段性总结(推荐)
2020/08/22 Javascript
python cookielib 登录人人网的实现代码
2012/12/19 Python
python使用pyhook监控键盘并实现切换歌曲的功能
2014/07/18 Python
在Django的视图中使用数据库查询的方法
2015/07/16 Python
深入讲解Python函数中参数的使用及默认参数的陷阱
2016/03/13 Python
Python3中使用urllib的方法详解(header,代理,超时,认证,异常处理)
2016/09/21 Python
Python 调用 zabbix api的方法示例
2019/01/06 Python
Django项目中实现使用qq第三方登录功能
2019/08/13 Python
世界领先的以旅馆为主的在线预订平台:Hostelworld
2016/10/09 全球购物
护理专科毕业推荐信
2013/11/10 职场文书
公司副总经理任命书
2014/06/05 职场文书
市场总监岗位职责
2015/02/11 职场文书
茶花女读书笔记
2015/06/29 职场文书
幼儿园国培研修日志
2015/11/13 职场文书
pytorch 梯度NAN异常值的解决方案
2021/06/05 Python
浅谈Redis跟MySQL的双写问题解决方案
2022/02/24 Redis
Python捕获、播放和保存摄像头视频并提高视频清晰度和对比度
2022/04/14 Python