zoukankan      html  css  js  c++  java
  • python调用C++ DLL 传参技巧

    结构体传参:http://www.jb51.net/article/52513.htm

    准备工作:

    C++文件(cpp):(注意在函数声明上加上extern "C" 的修饰)

    #include <stdio.h>
     
    extern "C" {
        __declspec(dllexport) int Double(int x);
        __declspec(dllexport) float floatAdd(float a,float b); 
        __declspec(dllexport) void HelloWorld(char * str); 
        __declspec(dllexport) void Ints(int * arr,int n); 
    }
     
    int Double(int x){
        return x*2;
    }
    
    float floatAdd(float a,float b) {
        return a+b;
    }
    
    void HelloWorld(char * str){
        puts(str);
    }
    
    void Ints(int * arr,int n){
        for(int i=0;i<n;i++){
            printf("%d ",arr[i]);
        }
        puts("");
    }

    用g++(mingw64位)编译为dll:

    g++ dlltest.cpp -shared -o dlltest.dll -Wl,--out-implib,dlltest.lib
    pause

    在python脚本中加载dll :

    from ctypes import *
    dll = cdll.LoadLibrary('DLL/dlltest.dll')

    1.如果不加任何修饰,默认传入参数为int,传出参数也为int

    2.对于int以外的类型(如float),需要声明python函数的传入参数类型传出参数类型

    fun.argtypes=[c_float,c_float]  #定义传参类型
    fun.restype=c_float             #定义返回值类型
    a=fun(c_float(1.4),c_float(1.2))
    print(type(a))
    print(a)

    输出:

    <class 'float'>
    2.5999999046325684

    3.对于字符串char* ,在声明传入参数类型时,需要声明为字符指针,然后分配一块char数组,最后把这个数组强制转换为字符指针

    并且,在把python脚本中的数据结构导入c++中时,需要把str转换为bytes或者bytesarray类型,并且进行迭代器分解

    hello=dll.HelloWorld
    hello.argtypes=[POINTER(c_char)]    #传入参数为字符指针
    STR=(c_char * 100)(*bytes("相信你还在这里",'utf-8')) #把一组100个的字符定义为STR
    cast(STR, POINTER(c_char))
    hello(STR)

    输出:

    相信你还在这里

    4.对于其他数据类型的数组,(例如int*),操作相似:

    Ints=dll.Ints
    Ints.argtypes=[POINTER(c_int),c_int]
    INT=(c_int * 100)(*[1,2,3]) #把列表传入变长参数args*中
    cast(INT, POINTER(c_int))
    Ints(INT,c_int(3))

    输出:

    1 2 3 

    5.对于返回值为数组的情况,可以直接使用索引去访问,但是下标操作[]不是从迭代器中取对象,而是地址偏移:

    def fillHoleCpp(im):
        dll = cdll.LoadLibrary("bfs.dll")
        bfs=dll.bfs
        bfs.argtypes = [POINTER(c_int),c_int]
        bfs.restype = POINTER(c_int)
        a = np.asarray(range(16), dtype=np.int32).reshape([4, 4])
        if not a.flags['C_CONTIGUOUS']:
            a = np.ascontiguous(a, dtype=a.dtype)  # 如果不是C连续的内存,必须强制转换
        IMG = cast(a.ctypes.data, POINTER(c_int))  # 转换为ctypes,这里转换后的可以直接利用cty
        cast(IMG, POINTER(c_int))
        length=a.size
        ans=bfs(IMG,c_int(length))
        print(type(ans))
        for i in range(0,length):
            print(ans[i],end=' ')
  • 相关阅读:
    iOS渠道分包2种模式之包内注入文件分包(iOS13验证签名问题)
    iOS13 新特性简介
    OC 字典dictionaryWithObjectsAndKeys报错
    博客迁移指南
    block内部实现原理(三)
    block内部实现原理(二)
    block内部实现原理(一)
    iOS:记一次Mac OS X 测试版(OS X EL Capitan) APP发布过程
    iOS: El Capitan Beta 下 Xcode6.4 不显示Scheme菜单
    iOS: UIWebView 中不加载图片(即浏览器常见的无图模式)
  • 原文地址:https://www.cnblogs.com/TQCAI/p/8881530.html
Copyright © 2011-2022 走看看