提示文章写完后目录可以自动生成如何生成可参考右边的帮助文档文章目录前言一、 ctypes库二、使用步骤1. c接口函数介绍2.引入库3.进行接口转换总结前言目前由于工作原因需在windows环境下利用python调用c语言写的动态链接库。 c/c代码由于其灵活性在底层算法中得到广泛使用。许多函数都采用 c/c语言进行编写要在其它语言中进行调用需要进行转换。由于此次的函数调用涉及到指针的传入传出涉及到许多知识点费了较大工夫才顺利完成特记录下来留作纪念以便以后查阅。一、 ctypes库ctypes是python的一个外部函数库提供了c的兼容数据类型允许调用dll或者共享库的函数。通过ctypes库能以接近c语言的方式在python中完成动态链接库中的调用。需要注意的是ctypes只提供了 c的兼容若要使用c代码则需要以c的方式进行编译即在c函数声明时加上前缀 extern C。ctypes提供了 c的兼容数据类型下表列举了两者之间基本数据类型的对应关系。ctypes数据类型c数据类型c_charcharc_bytecharc_ubyteunsigned charc_shortshortc_intintc_uintunsigned intc_longlongc_ulongunsigned longc_longlonglong longc_ulonglongunsigend long longc_floatfloatc_doubledoublec_char_pchar*c_wchar_pwchar_t*c_void_pvoid*二、使用步骤1. c接口函数介绍动态链接库中的 c函数主要是用于图像处理接收char*类型字符数组、 float参数、int*指针等参数类型同时返回int*数组其函数原型为int* code_generate_based_array(const char* msg, int ecLevel, int picWidth, unsigned char* imgData, float coderatio, int* dstWidth)接口说明——入参int* dstWidth会在函数内部进行改变得到最终图像的宽度——返回值int*是个整型数组存储处理完的图像颜色信息图像的宽度为dstWidth的值每个int值对应像素的rgb值即一个int值为r,g,b三通道的结合值rgb(int)(((int)r 16) | (unsigned short)(((unsigned short)g 8) | b));2.引入库在代码中需要处理图像所以引入了PIL库进行图像处理同时引入ctypes库进行动态链接库的函数转化及调用代码如下from ctypes import *from PIL import Image3.进行接口转换利用ctypes库将c接口函数表示成python代码。首先利用CDLL加载动态库dllCDLL(动态链接库路径)利用ctypes库进行c语言函数的转换dll.code_generate_based_array.argtypes[c_char_p,c_int,c_int,POINTER(c_ubyte),c_float,POINTER(c_int)] dll.code_generate_based_array.restypePOINTER(c_int)其中argtypes定义入参类型 restype定义返回类型。c语言中的指针可通过POINTER进行定义转换关系为—— const char*转化为c_char_p——int转化为c_int——unsigned char*转化为POINTER(c_ubyte)——float转化为c_float—— int*转化为POINTER(c_int)将原始图像读取转化为POINTER(c_ubyte)时需先定义一个数组其代码如下def get_img_byte_array(img,width,height): imgimg.convert(RGB) src_strlistimg.load() lenwidth*height*3 result(c_ubyte*len)() for i in range(0,height): for j in range(0,width): datasrc_strlist[j,i] result[(i*widthj)*3]data[0] result[(i*widthj)*31]data[1] result[(i*widthj)*32]data[2] return result这里有一个坑就是定义数组时的方式采用以下代码定义的是一维数组lenwidth*height*3 result(c_ubyte*len)()此时数组长度为width*height*3此时可采用下标result[i]的方式对数据进行操作而采用以下代码则定义的是三维数组result(c_ubyte*width*height*3)()需采用result[][][]的方式进行数据操作。下面将给出接口实际调用的完整代码from ctypes import * from PIL import Image def get_rgb(rgb): r(rgb0xFF0000)16; g(rgb0xFF00)8; b0xFFrgb; return (r,g,b) def get_rgb_matrix(img,width): return [get_rgb(img[i*widthj]) for i in range(width) for j in range(width)] get byte array from PIL image def get_img_byte_array(img,width,height): imgimg.convert(RGB) src_strlistimg.load() lenwidth*height*3 result(c_ubyte*len)() for i in range(0,height): for j in range(0,width): datasrc_strlist[j,i] result[(i*widthj)*3]data[0] result[(i*widthj)*31]data[1] result[(i*widthj)*32]data[2] return result dllCDLL(动态链接库路径) imgImage.open(rG:\pic\other\peo.jpeg) widthimg.size[0] heightimg.size[1] dll.code_generate_based_array.argtypes[c_char_p,c_int,c_int,POINTER(c_ubyte),c_float,POINTER(c_int)] dll.code_generate_based_array.restypePOINTER(c_int) dstWidthc_int(0) resultdll.code_generate_based_array(bhttps://www.vrcode.com,3,800,get_img_byte_array(img,width,height),0.5,dstWidth) img_outImage.new(RGB,(dstWidth.value,dstWidth.value)) rgbArrayget_rgb_matrix(result, dstWidth.value) img_out.putdata(rgbArray) img_out.save(test_out_2.png)经过测试上述代码能够完成图像的转换并保存在指定路径顺利完成接口的调用。总结以上就是今天要总结的内容本文介绍了python调用c语言动态链接库的过程这个过程中涉及到类型的转换、图像的处理、指针的处理并且过程中有几个坑通过探索顺利把坑填平实现了指定功能在此分享给需要的朋友。
python调用c/c++动态链接库时需注意的问题
提示文章写完后目录可以自动生成如何生成可参考右边的帮助文档文章目录前言一、 ctypes库二、使用步骤1. c接口函数介绍2.引入库3.进行接口转换总结前言目前由于工作原因需在windows环境下利用python调用c语言写的动态链接库。 c/c代码由于其灵活性在底层算法中得到广泛使用。许多函数都采用 c/c语言进行编写要在其它语言中进行调用需要进行转换。由于此次的函数调用涉及到指针的传入传出涉及到许多知识点费了较大工夫才顺利完成特记录下来留作纪念以便以后查阅。一、 ctypes库ctypes是python的一个外部函数库提供了c的兼容数据类型允许调用dll或者共享库的函数。通过ctypes库能以接近c语言的方式在python中完成动态链接库中的调用。需要注意的是ctypes只提供了 c的兼容若要使用c代码则需要以c的方式进行编译即在c函数声明时加上前缀 extern C。ctypes提供了 c的兼容数据类型下表列举了两者之间基本数据类型的对应关系。ctypes数据类型c数据类型c_charcharc_bytecharc_ubyteunsigned charc_shortshortc_intintc_uintunsigned intc_longlongc_ulongunsigned longc_longlonglong longc_ulonglongunsigend long longc_floatfloatc_doubledoublec_char_pchar*c_wchar_pwchar_t*c_void_pvoid*二、使用步骤1. c接口函数介绍动态链接库中的 c函数主要是用于图像处理接收char*类型字符数组、 float参数、int*指针等参数类型同时返回int*数组其函数原型为int* code_generate_based_array(const char* msg, int ecLevel, int picWidth, unsigned char* imgData, float coderatio, int* dstWidth)接口说明——入参int* dstWidth会在函数内部进行改变得到最终图像的宽度——返回值int*是个整型数组存储处理完的图像颜色信息图像的宽度为dstWidth的值每个int值对应像素的rgb值即一个int值为r,g,b三通道的结合值rgb(int)(((int)r 16) | (unsigned short)(((unsigned short)g 8) | b));2.引入库在代码中需要处理图像所以引入了PIL库进行图像处理同时引入ctypes库进行动态链接库的函数转化及调用代码如下from ctypes import *from PIL import Image3.进行接口转换利用ctypes库将c接口函数表示成python代码。首先利用CDLL加载动态库dllCDLL(动态链接库路径)利用ctypes库进行c语言函数的转换dll.code_generate_based_array.argtypes[c_char_p,c_int,c_int,POINTER(c_ubyte),c_float,POINTER(c_int)] dll.code_generate_based_array.restypePOINTER(c_int)其中argtypes定义入参类型 restype定义返回类型。c语言中的指针可通过POINTER进行定义转换关系为—— const char*转化为c_char_p——int转化为c_int——unsigned char*转化为POINTER(c_ubyte)——float转化为c_float—— int*转化为POINTER(c_int)将原始图像读取转化为POINTER(c_ubyte)时需先定义一个数组其代码如下def get_img_byte_array(img,width,height): imgimg.convert(RGB) src_strlistimg.load() lenwidth*height*3 result(c_ubyte*len)() for i in range(0,height): for j in range(0,width): datasrc_strlist[j,i] result[(i*widthj)*3]data[0] result[(i*widthj)*31]data[1] result[(i*widthj)*32]data[2] return result这里有一个坑就是定义数组时的方式采用以下代码定义的是一维数组lenwidth*height*3 result(c_ubyte*len)()此时数组长度为width*height*3此时可采用下标result[i]的方式对数据进行操作而采用以下代码则定义的是三维数组result(c_ubyte*width*height*3)()需采用result[][][]的方式进行数据操作。下面将给出接口实际调用的完整代码from ctypes import * from PIL import Image def get_rgb(rgb): r(rgb0xFF0000)16; g(rgb0xFF00)8; b0xFFrgb; return (r,g,b) def get_rgb_matrix(img,width): return [get_rgb(img[i*widthj]) for i in range(width) for j in range(width)] get byte array from PIL image def get_img_byte_array(img,width,height): imgimg.convert(RGB) src_strlistimg.load() lenwidth*height*3 result(c_ubyte*len)() for i in range(0,height): for j in range(0,width): datasrc_strlist[j,i] result[(i*widthj)*3]data[0] result[(i*widthj)*31]data[1] result[(i*widthj)*32]data[2] return result dllCDLL(动态链接库路径) imgImage.open(rG:\pic\other\peo.jpeg) widthimg.size[0] heightimg.size[1] dll.code_generate_based_array.argtypes[c_char_p,c_int,c_int,POINTER(c_ubyte),c_float,POINTER(c_int)] dll.code_generate_based_array.restypePOINTER(c_int) dstWidthc_int(0) resultdll.code_generate_based_array(bhttps://www.vrcode.com,3,800,get_img_byte_array(img,width,height),0.5,dstWidth) img_outImage.new(RGB,(dstWidth.value,dstWidth.value)) rgbArrayget_rgb_matrix(result, dstWidth.value) img_out.putdata(rgbArray) img_out.save(test_out_2.png)经过测试上述代码能够完成图像的转换并保存在指定路径顺利完成接口的调用。总结以上就是今天要总结的内容本文介绍了python调用c语言动态链接库的过程这个过程中涉及到类型的转换、图像的处理、指针的处理并且过程中有几个坑通过探索顺利把坑填平实现了指定功能在此分享给需要的朋友。