Python使用ctypes访问C代码

工具:CodeBlocks

新建一个分享库工程( Shared library ),随便编写一个C代码的函数

// test.c

#include <stdio.h>

int fib(int n)
{
    if( n == 0 || n == 1)
    {
        return 1;
    }
    else
    {
        return fib(n-1) + fib(n-2);
    }
}


编译,在bin/Debug/目录中生成libtest.dll动态链接库文件,该文件可以通过ctypes模块进行访问使用,在该文件目录下新建一个test.py文件

# test.py

import ctypes
import os

_file_path = os.path.join(os.path.dirname(__file__), 'libtest.dll')
_mod = ctypes.cdll.LoadLibrary(_file_path)   #加载动态库文件,返回一个类对象 <class 'ctypes.CDLL'>


# int fib(int n)
fib = _mod.fib               #获取类方法
fib.argtypes = (ctype_int,)  #配置参数类型(tuple)
fib.restype = ctypes_int     #配置返回值类型


#现在可以直接使用fib函数了
for i in range(10):
    print( fib(i), end=' ' )


C函数的指针作为参数情况

// 参数有指针的函数
int divide(int a, int b, int *remainder) {
    int quot = a / b;
    *remainder = a % b;
    return quot;
}


# 相应的处理办法

# int divide(int, int, int *)
_divide = _mod.divide
_divide.argtypes = (ctypes.c_int, ctypes.c_int, ctypes.POINTER(ctypes.c_int))   
_divide.restype = ctypes.c_int

def divide(x, y):
  rem = ctypes.c_int()
  quot = _divide(x, y, rem)
  return quot,rem.value

C函数的数组作参数的情况 

double avg(double *a, int n) {
    int i;
    double total = 0.0;
    for (i = 0; i < n; i++) {
        total += a[i];
    }
    return total / n;
# 对于C中的数组,Python中没有固定的对应类型,所以要分类处理:
# Define a special type for the 'double *' argument class DoubleArrayType: def from_param(self, param): #对传进来的参数进行分发 typename = type(param).__name__ if hasattr(self, 'from_' + typename): return getattr(self, 'from_' + typename)(param) elif isinstance(param, ctypes.Array): return param else: raise TypeError("Can't convert %s" % typename) # Cast from array.array objects def from_array(self, param): if param.typecode != 'd': raise TypeError('must be an array of doubles') ptr, _ = param.buffer_info() return ctypes.cast(ptr, ctypes.POINTER(ctypes.c_double)) # Cast from lists/tuples def from_list(self, param): val = ((ctypes.c_double)*len(param))(*param) return val from_tuple = from_list # Cast from a numpy array def from_ndarray(self, param): return param.ctypes.data_as(ctypes.POINTER(ctypes.c_double)) DoubleArray = DoubleArrayType() _avg = _mod.avg _avg.argtypes = (DoubleArray, ctypes.c_int) _avg.restype = ctypes.c_double def avg(values): return _avg(values, len(values))
KEEP LEARNING!
原文地址:https://www.cnblogs.com/roronoa-sqd/p/5446524.html