zoukankan      html  css  js  c++  java
  • 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!
  • 相关阅读:
    How to function call using 'this' inside forEach loop
    jquery.validate.unobtrusive not working with dynamic injected elements
    Difference between jQuery.extend and jQuery.fn.extend?
    Methods, Computed, and Watchers in Vue.js
    Caution using watchers for objects in Vue
    How to Watch Deep Data Structures in Vue (Arrays and Objects)
    Page: DOMContentLoaded, load, beforeunload, unload
    linux bridge
    linux bridge
    EVE-NG网卡桥接
  • 原文地址:https://www.cnblogs.com/roronoa-sqd/p/5446524.html
Copyright © 2011-2022 走看看