zoukankan      html  css  js  c++  java
  • python调用.so

    python调用动态链接库的基本过程

    动态链接库在Windows中为.dll文件,在linux中为.so文件。以linux平台为例说明python调用.so文件的使用方法。
    本例中默认读者已经掌握动态链接库的生成方法,如果不太清楚的可以参考动态链接库的使用
    调用上例动态链接库的使用中的sum.so

    import ctypes
    so = ctypes.CDLL('./sum.so')
    
    print "so.sum(50) = %d" % so.sum(50)
    so.display("hello world!")
    print "so.add() = %d" % so.add(ctypes.c_float(2), ctypes.c_float(2010))
    

    output

    so.sum(50) = 1275
    hello world!
    so.add() = 2012
    

    注意:

    • 如果python在调用C函数内部出现了问题,系统不会提示具体出现什么问题,只会提示"segmentation fault"。所以最好是先用C语言调用该动态库验证没有问题了再提供给python调用。
    • python传参给C函数时,可能会因为python传入实参与C函数形参类型不一致会出现问题( 一般int, string不会有问题,float要注意 )。这时需要在python调用时传入的实参做一个类型转换(见so.add(float, float)函数的调用)。转换方式见下表:

    args|center

    数组的传入传出

    如果将python中list传入C函数数组,则需要提前转换。

    import ctypes
    pyarray = [1, 2, 3, 4, 5]
    carrary = (ctypes.c_int * len(pyarray))(*pyarray) //有点类似malloc的方式生成carray
    print so.sum_array(carray, len(pyarray))
    

    refer

    如果如果需要将C array返回python,需要提前把array传入,然后在C函数中修改,返回时再把c array转换为np.array

    pyarray = [1,2,3,4,5,6,7,8]
    carray = (ctypes.c_int*len(pyarray))(*pyarray)
    so.modify_array(carray, len(pyarray))
    print np.array(carray)
    

    output

    [10 20 30 40 50 60 70 80]
    

    也可以用形参方式提前定义函数接口,然后再传入numpy结构

    import ctypes
    import numpy as np
    from numpy.ctypeslib import ndpointer
    so = ctypes.CDLL('./sum.so')
    pyarray = np.array([1,2,3,4,5,6,7,8], dtype="int32")
    fun = so.modify_array
    fun.argtypes = [ndpointer(ctypes.c_int), ctypes.c_int]
    fun.restype = None
    fun(pyarray, len(pyarray))
    print np.array(pyarray)
    

    注意:numpy中的数据类型指定很重要,即dtype的设定

    图片的传入传出

    转递数据域

    背景知识:
    python中的opencv图片是用numpy的方式保存的,而opencv3 C语言的图片数据结构为cvMat (IplImage已经逐弃用)
    所以需要把python中numpy图片转换为ctypes.POINTER(ctypes.c_ubyte)的指针转入其数据域,再将其行列信息传入,就可以在C中从最底层初始化一个CvMat,如果要初始化一个别数据结构的图片也是同理(如darknet的image,caffe的blob)
    python numpy image 转换为 C pointer的方法

    python_frm.ctypes.data_as(C.POINTER(ctypes.c_ubyte))
    

    注意:传入numpy image前一定要确保numpy image是numpy array数据类型
    比如我遇到的bug

    image = cv2.imread("xxx.jpg");
    

    image传入ctypes_so.fun之中图片是有效的,

    image = whl_img[y1:y2, x1:x2]
    

    这时候进入ctypes_so.fun的图片会变成一个乱码
    即,crop之后的numpy image的type虽然也为numpy array,但实际传入的image data却不正确
    解决方法
    无论是何种方式得到的numpy image,都强行转换为numpy array,再传入ctypes_so.fun

    image = numpy.array(image)
    

    可以解决这个bug
    refence

    如果使用opencv2 可以考虑直接将numpy image转换为IplImage

    opencv3 python已经不支持cv2.cv的函数了
    但Opencv2可能还可以尝试以下方法
    numpy image to iplimage

    python调用C++中的类

    因为python不能直接调用C++中的类,所以必须把C++中的类转换为C的接口
    转换原则

    • 所有的C++关键字及其特有的使用方式均不能出现在.h文件里,.h中仅有C函数的包装函数声明
    • 在class.cpp中实现对类的成员函数接口转换的函数,包括对类内成员的读写函数get() and set()
    • 如果要在包装函数中要实例化对象,尽量用new constructor()的将对象的内存实例化在堆中,否则对象会被析构
    • 记得在所有包含函数声明的文件中加入以下关键字,声明该函数为C函数,否则该函数的符号不会记录在二进制文件中
    #ifdef __cplusplus
    extern "C" {
    #endif
    xxxxxx function declaration xxxxx
    #ifdef __cplusplus
    }
    #endif
    

    code
    refer
    refer

  • 相关阅读:
    PyQt作品 – PingTester – 多点Ping测试工具
    关于和技术人员交流的一二三
    Pyjamas Python Javascript Compiler, Desktop Widget Set and RIA Web Framework
    Hybrid Qt applications with PySide and Django
    pyjamas build AJAX apps in Python (like Google did for Java)
    PyQt 维基百科,自由的百科全书
    InfoQ:请问为什么仍要选择Java来处理后端的工作?
    Eric+PyQt打造完美的Python集成开发环境
    python select module select method introduce
    GUI Programming with Python: QT Edition
  • 原文地址:https://www.cnblogs.com/fariver/p/6573112.html
Copyright © 2011-2022 走看看