|
目录为什么需要调用动态链接库一个例子有参数指定参数类型指定返回值类型复合类型参数导出c++函数为什么需要调用动态链接库有大量优秀的库,直接以本地库(机器代码)提供的,这些库基本都是c/c++语言编写的。通常要调用它们,需要使用c/c++语言。如果你的应用,已经用python开发了,能不能用python直接调用这些库,使用这些库的功能呢?当然可以。python语言的官方解释器CPython本身就是用C语言开发的,可以很方便的从python代码中调用动态链接库。动态链接库,在不同的操作系统(Windows、Linux),文件格式不同,但是python调用它们的方法都差不多。我们这里以Windows平台的dll为例。参考https://docs.python.org/3/library/ctypes.html一个例子点击这里下载https://cdn2.byhy.net/files/py/etc/Dll1.dll动态链接库中有这样的函数voidSayHello(){MessageBox(NULL,TEXT("向您问好~~~"),TEXT("你好"),MB_OK);}使用如下代码加载dll,并且调用函数SayHellofromctypesimport*#LoadDLLintomemory.lib=CDLL("e:\\Dll1.dll")lib.SayHello()有参数fromctypesimport*#LoadDLLintomemory.lib=CDLL("e:\\Dll1.dll")lib.StrAppend('你也好')ret=lib.IntAdd(3,4)print(ret)通过python可以很方便的使用不同参数调用,无须编译运行。如果是测试,甚至比直接用c语言写测试代码方便。上面的IntAdd和StrAppend,我们直接使用了Python对象作为参数传入。实际上,底层的ctypes库调用c语言库,不能直接传递python对象的,需要转化为c语言接口对应的类型。它会根据我们使用的python对象类型,猜测应该转化为什么类型的数据。Python数据对象和C语言的数据对象的对应关系见https://docs.python.org/3/library/ctypes.html#fundamental-data-types特别要注意w_char和char的区别,前者对应python3中的字符串,后者对应字节串指定参数类型前面的示例,我们直接使用了Python对象作为参数传入。好像也没有什么问题。但是建议大家最好还是直接告诉ctypes你的参数类型。特别是从python对象类型不能唯一对应c语言类型的。比如charshortintlong这些。否则可能带来意想不到的问题。参考https://stackoverflow.com/questions/24377845/ctype-why-specify-argtypes怎么告诉呢?fromctypesimport*#LoadDLLintomemory.lib=CDLL("e:\\Dll1.dll")lib.StrAppend.argtypes=[c_wchar_p]lib.StrAppend('你说话')也可以lib.StrAppend(c_wchar_p('也好'))指定返回值类型看看下面的例子fromctypesimport*lib=CDLL("e:\\Dll1.dll")ret=lib.IntAdd(3,4)print(ret)ret2=lib.StrAppend('你好')print(ret2)第1个是对的,第2个怎么是数字?返回类型,ctypes缺省认为是Cint类型不是int类型的,可以通过function对象的restype属性指定fromctypesimport*#LoadDLLintomemory.lib=CDLL("e:\\Dll1.dll")ret=lib.IntAdd(3,4)print(ret)lib.StrAppend.restype=c_wchar_pret2=lib.StrAppend('你好')print(ret2)lib.BytesAppend.restype=c_char_pret3=lib.BytesAppend(b'\x39\x99')print(ret3)复合类型参数参考https://stackoverflow.com/questions/4351721/python-ctypes-passing-a-struct-to-a-function-as-a-pointer-to-get-back-data导出c++函数由于c++对符号名的魔改,c++语法编译的函数,直接ctypes调用会发现找不到函数要调用怎么办?一种方法是加上 extern"C" 的说明,重新编译动态链接库。extern"C"__declspec(dllexport)voidSayHello();如果没有源代码,可以通过工具(比如dllexp)找到这个dll导出的c++修改后函数名字,然后调用它参考https://stackoverflow.com/questions/21184911/c-dll-called-from-python
|
|