Python Ctypes调用dll so动态库链接库
ctypes是python的一个函数库,提供和C语言兼容的数据类型,可以直接调用动态链接库中的导出函数。
本文基于的系统以及软件环境:
1.win 10
2.python-3.8.2-amd64解释器
3.PyCharm Community Edition 2020.1.1 x64
4.vs_community2019
Windwos动态库链接库
1._declspec(dllexport)
2.extern “C”
3.库在系统目录或当前目录执行
4.与python库查找路径无关sys.path
Windows dll程序
//typesdll.cpp
#include <stdio.h>
extern "C" __declspec(dllexport) void TestCtypes() {
printf("In C TestCtypes fun\n");
}
python程序
from ctypes import *
import os
def test_ctypes():
print('test_ctypes')
print(os.getcwd()) # 显示当前路
#导入库 注意windows 此处不用加.dll后缀名,直接写动态库名称即可,如下
c_dll = CDLL(r".\\testCtypes") #Try using the full path with constructor syntax
#c_dll = CDLL("D:\\Python_study\\python_c\\testCtypes")
#c_dll = WinDLL("D:\\Python_study\\python_c\\testCtypes.dll")
#调用方法 extern "C" __declspec(dllexport) void TestCtypes()
c_dll.TestCtypes()
#FileNotFoundError: Could not find module 'testCtypes' (or one of its dependencies).
# OSError: [WinError 193] %1 不是有效的 Win32 应用程序。
# 注意必须要版本匹配,如python 32bit匹配调用win32 dll,
# 执行结果:
#test_ctypes
#D:\Python_study\python_c
#In C TestCtypes fun
传递数值类型参数
Windows dll程序
extern "C" __declspec(dllexport) void TestNumber(int x ,float y,bool i_bool) {
printf("In C TestNumber fun\n");
printf("int x = [%d]\n",x);
printf("float y = [%lf] \n",y);
printf("bool ibnu = [%d]\n", i_bool);
}
Python程序
from ctypes import *
def TestNumber():
print('TestNumber')
#导入库 注意windows 此处不用加.dll后缀名,直接写动态库名称即可,如下
c_dll = CDLL(r".\\testCtypes")
try:
#TestNumber error argument 2: <class 'TypeError'>: Don't know how to convert parameter 2
#c_dll.TestNumber(101,123.56,True)
c_dll.TestNumber(101, c_float(123.56), True)
except Exception as ex:
print('TestNumber error' ,ex)
if __name__ == '__main__':
TestNumber()
# TestNumber
# In C TestNumber fun
# int x = [101]
# float y = [123.559998]
# bool ibnu = [1]
传递字符串参数
string和byte
c_wchar_p() 和 c_char_p()
可修改字符串create_string_buffer
Windows dll程序
// char 类型 c_char_p
extern "C" __declspec(dllexport) void TestStringA(const char* str, int size) {
printf("In C TestStringA fun\n");
printf("str = [%s] \n", str);
printf("int size = [%d]\n", size);
}
// wchar_t 类型 c_wchar_p
extern "C" __declspec(dllexport) void TestStringW(const wchar_t* str, int size) {
printf("In C TestStringB fun\n");
wprintf(L"str = [%ls] \n", str);
printf("int size = [%d]\n", size);
}
// 如果在C语言中需要修改的时候可以采用
extern "C" __declspec(dllexport) void TestStringBuffer(char * str) {
printf("In C TestStringBuffer fun\n");
printf("old str = [%s]\n", str);
memcpy(str, "update str in C ",15);
str[15] = '\0';
//str[0] = '#';
//str[1] = 'S';
printf("new str = [%s]\n",str);
}
Python程序
def test_String(str):
print('test_String')
#导入库 注意windows 此处不用加.dll后缀名,直接写动态库名称即可,如下
c_dll = CDLL(r".\\testCtypes")
try:
c_dll.TestStringA(c_char_p(str),len(str))
except Exception as ex:
print('TestStringA error' ,ex)
def test_StringW(wstr):
print('test_StringW')
#导入库 注意windows 此处不用加.dll后缀名,直接写动态库名称即可,如下
c_dll = CDLL(r".\\testCtypes")
try:
c_dll.TestStringW(c_wchar_p(wstr),len(wstr))
except Exception as ex:
print('TestStringW error' ,ex)
def test_String_Buffer(str):
print('test_String_Buffer')
#导入库 注意windows 此处不用加.dll后缀名,直接写动态库名称即可,如下
c_dll = CDLL(r".\\testCtypes")
try:
buffer = create_string_buffer(str)
c_dll.TestStringBuffer(buffer)
except Exception as ex:
print('test_String_Buffer error',ex)
if __name__ == '__main__':
# TestStringA error bytes or integer address expected instead of str instance
# python必须为byte对象
#test_String("Hello I am python char")
#test_String(b"Hello I am python char")
#test_String
# In C TestStringA fun
# str = [Hello I am python char]
# int size = [22]
#wstr = 'wstr is python wide string'
#test_StringW(wstr)
#test_StringW
#In C TestStringB fun
#s t r = [ w s t r i s p y t h o n w i d e s t r i n g ]
# int size = [26]
str = b'I am python str I am python str I am python str I am python str'
test_String_Buffer(str)
"""
test_String_Buffer
In C TestStringBuffer fun
old str = [I am python str I am python str I am python str I am python str]
new str = [update str in C]
"""