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遍历指定城市的一周气温
Mar 31 Python
Python和C/C++交互的几种方法总结
May 11 Python
python远程连接MySQL数据库
Apr 19 Python
基于python实现高速视频传输程序
May 05 Python
python 缺失值处理的方法(Imputation)
Jul 02 Python
Python获取好友地区分布及好友性别分布情况代码详解
Jul 10 Python
这可能是最好玩的python GUI入门实例(推荐)
Jul 19 Python
django之状态保持-使用redis存储session的例子
Jul 28 Python
Python数据分析pandas模块用法实例详解
Nov 20 Python
浅析Python 简单工厂模式和工厂方法模式的优缺点
Jul 13 Python
python如何变换环境
Jul 21 Python
python 如何对logging日志封装
Dec 02 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模拟socket一次连接,多次发送数据的实现代码
2011/07/26 PHP
程序员的表白神器“520”大声喊出来
2016/05/20 PHP
PHP+Mysql+Ajax实现淘宝客服或阿里旺旺聊天功能(前台页面)
2017/06/16 PHP
PHP简单实现记录网站访问量功能示例
2018/06/06 PHP
SyntaxHighlighter语法高亮插件使用说明
2011/08/14 Javascript
Array.prototype.concat不是通用方法反驳[译]
2012/09/20 Javascript
js鼠标点击图片实现随机变换图片的方法
2015/02/16 Javascript
js面向对象之常见创建对象的几种方式(工厂模式、构造函数模式、原型模式)
2015/11/09 Javascript
JS动态插入并立即执行回调函数的方法
2016/04/21 Javascript
JS中innerHTML和pasteHTML的区别实例分析
2016/06/22 Javascript
jQuery实现用户输入自动完成功能
2017/02/13 Javascript
bootstrap模态框示例代码分享
2017/05/17 Javascript
Iscrool下拉刷新功能实现方法(推荐)
2017/06/26 Javascript
JavaScript仿微信(电话)联系人列表滑动字母索引实例讲解(推荐)
2017/08/16 Javascript
vue用Object.defineProperty手写一个简单的双向绑定的示例
2018/07/09 Javascript
layui实现数据分页功能(ajax异步)
2019/07/27 Javascript
python通过字典dict判断指定键值是否存在的方法
2015/03/21 Python
python opencv人脸检测提取及保存方法
2018/08/03 Python
基于Python的Post请求数据爬取的方法详解
2019/06/14 Python
python把ipynb文件转换成pdf文件过程详解
2019/07/09 Python
Python栈的实现方法示例【列表、单链表】
2020/02/22 Python
PyCharm 2020 激活到 2100 年的教程
2020/03/25 Python
Tensorflow加载Vgg预训练模型操作
2020/05/26 Python
基于Pyinstaller打包Python程序并压缩文件大小
2020/05/28 Python
Python实现Appium端口检测与释放的实现
2020/12/31 Python
python中K-means算法基础知识点
2021/01/25 Python
canvas环形倒计时组件的示例代码
2018/06/14 HTML / CSS
eBay瑞士购物网站:eBay.ch
2018/12/24 全球购物
出纳岗位职责
2013/11/09 职场文书
共产党员承诺书
2014/03/25 职场文书
九一八事变演讲稿
2014/09/05 职场文书
一般基层干部群众路线教育实践活动个人对照检查材料
2014/11/04 职场文书
教学督导岗位职责
2015/04/10 职场文书
开展警示教育活动总结
2015/05/09 职场文书
Python使用random模块实现掷骰子游戏的示例代码
2021/04/29 Python
Python实现批量自动整理文件
2022/03/16 Python