将C程序封装成python库
本文简单说明了将C函数封装成python库的过程。
之前写了如何用ctypes
模块调用C的共享库,这次我们尝试直接将C程序打包成python的库文件。具体的细节可以查询 python官方文档。
前期准备
为了将C函数封装成python库,我们必须在系统中安装python开发包——python-dev
,具体方法可以根据系统的不同,自行去网上搜索,我们在这里不再赘述。
如果使用系统原生的python2或者直接安装的python3,可直接略过以下内容。但如果系统安装的是Anaconda
,那们在编译C语言时可能会出现以下情况:
fatal error: Python.h: No such file or directory
导致问题的原因在于,Python.h文件在Anaconda文件目录下,不在GCC的默认加载库文件的路径里,所以编译时会导致GCC无法找到头文件。
我们先找到系统中python.h的位置:
sudo find / -name Python.h 2>/dev/null
然后将文件的路径加载入GCC的路径中:
export C_INCLUDE_PATH=对应路径
C程序
接下来我们就需要对原有的c程序进行修饰,完成对于输入和输出数据的格式转换。以下是一个简单的计算斐波那契数列的小程序。头文件代码如下:
/* fib.h */
#ifndef FIB_H_
#define FIB_H_
static int fib(int num);
#endif
主程序代码如下:
/* fib.c */
#include <stdio.h>
#include <Python.h>
#include "fib.h"
/* The function to calculate fibonacci sequence */
static int
fib(int num)
{
int pre = 0, ppre = 1;
int media;
for (int i = 0; i < num; i++) {
media = pre;
pre = ppre + pre;
ppre = media;
}
return pre;
}
/* Wrap the original function to python object */
static PyObject *
py_fib(PyObject *self, PyObject *args)
{
int num;
int result;
// transform python object to c int
if (!PyArg_ParseTuple(args, "i", &num))
return NULL;
result = fib(num);
// transform c int to python object
return Py_BuildValue("i", result);
}
/* Define the methods in module */
static PyMethodDef fibmethods[] = {
{"fib", py_fib, METH_VARARGS},
{NULL, NULL, 0, NULL}
};
/* Define the module */
static struct PyModuleDef fibmodule = {
PyModuleDef_HEAD_INIT,
"Fib", /* name of module */
NULL, /* module documentation, may be NULL */
-1, /* size of per-interpreter state of the module,
or -1 if the module keeps state in global variables. */
fibmethods
};
/* initialization function */
PyMODINIT_FUNC
PyInit_Fib(void)
{
return PyModule_Create(&fibmodule);
}
主程序代码主要分为3部分:
fib
函数:计算斐波那契数列的c函数py_fib
函数:对fib
函数进行封装,将输入输出值的类型由c的原生类型转换为python类型,函数具体意义可以查询 python C API manualfibmethods
,fibmodule
,PyInit_Fib
:对模块的方法,名字,内容进行定义,并初始化
python库安装
接着我们写python库的安装程序:
from setuptools import setup
from distutils.core import Extension
version = '0.10'
MOD = 'Fib'
source = 'fib.c'
setup(name = MOD,
version = version,
description = "a fib sequence calculate package",
classifiers=[
"Programming Language :: Python",
],
author = 'Hanfeng Zhang',
ext_modules = [Extension(MOD, sources = ['fib.c',])],
install_requires=[
'setuptools',
]
)
用下列命令行安装python库:
python setup.py build
python setup.py install
安装完毕后,进入python,检查新的库能否正常使用:
>>> import Fib
>>> Fib.fib(10)
55
库安装成功!