ctypes
是python标准库的一员,相当于为python与C语言之间假设了一道桥梁,使得二者之间的混合编程成为可能。本文就演示一下,在Python中通过ctypes
模块对C语言的dll文件进行调用的过程。
例如我们用C语言写一个希尔排序
//sort.h
#include
void ShellSort(double *arr, int n);
//sort.c
#include "sort.h"
void ShellSort(double *arr, int n){
double temp;
int j;
for(int nSub=n/2; nSub>0; nSub/=2)
for(int i=nSub; i<n; i++){
temp = arr[i];
for(j=i-nSub; j>=0 && temp<arr[j]; j-=nSub)
arr[j+nSub] = arr[j];
arr[j+nSub] = temp;
}
}
先写一个test.c
做测试。
//test.c
#include "sort.h"
int main(){
double arr[5] = {1,3,5,4,2};
ShellSort(arr,5);
for(int i=0; i<5; i++)
printf("%lf ", arr[i]);
return 0;
}
首先通过gcc -shared -o
将sort.c
变成sort.dll
,再将sort.dll
链接到test.c
中,从而生成test.exe
。gcc会自动将-l
后面的sort
识别为sort.dll
。
>gcc -shared -o sort.dll sort.c
>gcc -o test.exe .\test.c -L./ -lsort
>test.exe
1.000000 2.000000 3.000000 4.000000 5.000000
test.exe
成功运行,说明我们这个函数是正确的。
接下来需要在python
中通过ctypes
进行调用。务必注意python和dll须有相同的数据位数。在windows下,如果用mingw中的gcc,只能编译32位程序,而若Python为64位,则会报出如下错误
>>> import ctypes
>>> dll = ctypes.CDLL("./sort.dll")
Traceback (most recent call last):
File "" , line 1, in <module>
File "C:\Python310\lib\ctypes\__init__.py", line 374, in __init__
self._handle = _dlopen(self._name, mode)
OSError: [WinError 193] %1 不是有效的 Win32 应用程序。
为了解决这个问题,需要下载安装mingw-w64。
在正确安装并设置mingw-w64
之后,进入python
>>> import ctypes
>>> dll = ctypes.CDLL("./sort.dll")
>>> tenValues = ctypes.c_double * 10 #新建一个长度位10的double型数组
>>> v = tenValues(1,3,5,7,9,8,6,4,2,10)
>>> dll.ShellSort(v,10)
0
>>> for i in v:print(i,end=' ')
...
1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0 10.0
可见希尔排序的确起到了作用。
ctypes | c数据类型 | |
---|---|---|
c_bool |
_Bool | |
c_byte ,c_int8 |
char | |
c_short , c_int16 |
short | |
c_int , c_int32 |
int | |
c_long |
long | |
c_longlong , c_int64 |
long long | |
c_char , c_char_p |
char, char* | |
c_double , c_float |
double, float | |
c_longdouble |
long double | |
c_size_t |
size_t | |
c_ssize_t |
ssize_t | |
c_ubyte , c_uint8 |
unsigned char | |
c_ushort , c_uint16 |
unsigned short | |
c_uint , c_uint32 |
unsigned int | |
c_ulong |
unsigned long | |
c_ulonglong , c_uint64 |
unsigned long long | |
c_void_p |
void * | |
c_wchar |
wchar_t * | |
c_wchar_p |
wchar_p * |