zoukankan      html  css  js  c++  java
  • Python调用C/C++动态链接库的方法详解

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

    投稿:shichen2014

    这篇文章主要介绍了Python调用C/C++动态链接库的方法,需要的朋友可以参考下

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

  • 相关阅读:
    JS 反射机制及 Reflect 详解
    React Hooks
    深入理解 React setState
    React 函数组件和类组件的区别
    tsconfig.json 编译器配置大全
    React TS 解决不声明变量类型时的报错问题
    JSX onClick 和 HTML onclick 的区别
    深入理解 ES6 Generator
    JS 算法与数据结构之队列
    深入理解 ES6 Proxy
  • 原文地址:https://www.cnblogs.com/lovebay/p/4936435.html
Copyright © 2011-2022 走看看