python封装C库实现对C代码调用

Python封装C库实现对C库调用

 

 本文由希希大队长创作,请勿盗链

 

在实际开发过程中,由于有些经典高效的库是由C写的,尤其涉及到计算密集型的,python很难做到高效,因此我们需要实现将C库作为模块引入python,供我们使用,在这个过程里面,希望大家少踩坑

我们来以一个小demo为例,这里首先展示下demo目录结构

 

demo
  -- install.sh # sh构建文件
  -- main.py    # 测试文件
  -- setup.py # 构建py扩展库文件
  -- test.c   # C扩展库

install.sh

python3 setup.py install

rm -rf ./dist
rm -rf ./build

setup.py

from distutils.core import setup, Extension

setup(name='aaa', # 定义的模块名
     version='1.0',
     ext_modules=[
         Extension('aaa', ['test.c']) # aaa为c文件中定义的模块名,test.c为 c文件路径
    ]
    )

test.c 简单的fib函数封装,以下内容为python3的封装方式,python2可自行百度

#include <Python.h>

//a func to calc fib numbers
int cFib(int n)
{
   if (n<2) return n;
   return cFib(n-1) + cFib(n-2);
}

// 实现c与py参数返回值桥接
static PyObject* fib(PyObject* self,PyObject* args)
{
   int n;
   if (!PyArg_ParseTuple(args,"i",&n))
       return NULL;
   return Py_BuildValue("i",cFib(n));
}

// 定义模块包含的功能/函数
static PyMethodDef module_methods[] = {
  {"fib",(PyCFunction) fib, METH_VARARGS,"calculates the fibonachi number"},
  {NULL,NULL,0,NULL}
};

// 封装一个模块结构体
static struct PyModuleDef aaa =
{
   PyModuleDef_HEAD_INIT,
   "aaa", /* name of module */
   "",          /* module documentation, may be NULL */
   -1,          /* size of per-interpreter state of the module, or -1 if the module keeps state in global variables. */
   module_methods
};

// init该模块为py模块
PyMODINIT_FUNC PyInit_aaa(void)
{
   return PyModule_Create(&aaa);
}

main.py 测试c扩展库是否构建成功

import aaa

if __name__ == '__main__':

   for num in range(10):
       print(aaa.fib(num))
        

需要注意的是,你期待生成的模块名需与c文件中几个关键的名称须保持一致

也就是以上例子中setup.py和test.c中所有为aaa的地方

以上文件准备好后,开始打包

首先进入demo目录

cd demo
 执行构建sh文件
install.sh

不报错即构建成功

测试:

在demo目录下执行

python3 main.py

正常输出:

0
1
1
2
3
5
8
13
21
34

如果执行测试脚本时提示导入模块问题,例:

ImportError:The dynamic module does not define the init function

请检查 期待生成的模块名需与c文件中几个关键的名称须保持一致,即以上例子中setup.py和test.c中所有为aaa的地方

 

本文完结!

 

 

 
posted @ 2021-03-08 11:36  希希大队长  阅读(570)  评论(0编辑  收藏  举报