当前位置: 移动技术网 > IT编程>脚本编程>Python > Python调用C/C++动态链接库的方法详解

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

2019年03月28日  | 移动技术网IT编程  | 我要评论

本文以实例讲解了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库的功能还有待继续探索

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网