1、在文件第一行包含python调用扩展的头文件

#include <Python.h>

2、用原生C写好需要调用的函数

int add_one(int a){
return a + ;
}

3、用python规定的调用方式,加一层C语言的包装,包装内容包括

  a.定义一个新的静态函数,接受两个PyObject *参数,返回一个PyObject *值

  b.解析第二个输入的PyObject *(通过PyArg_ParseTuple等方法),把python输入的变量变成C的变量

  c.调用原生C函数

  d.将调用返回的C变量,转换为PyObject*或其子类(通过PyLong_FromLong)等方法,并返回

static PyObject * py_add_one(PyObject *self, PyObject *args){
int num;
if (!PyArg_ParseTuple(args, "i", &num)) return NULL;
return PyLong_FromLong(add_one(num));
}

4、创建一个数组,来指明python可调用这个扩展的函数。

其中"add_one",代表编译后python调用时希望使用的函数名,

py_add_one,代表调用当前C代码中的哪个函数,

METH_VARARGS,代表函数的参数传递形式,主要包括位置参数和关键字参数两种,

关于这个变量具体参考https://docs.python.org/3/extending/extending.html的1.4节。

如果希望添加新的函数,则在最后的{NULL, NULL}之前按同样格式填写新的调用信息。

static PyMethodDef Methods[] = {
{"add_one", py_add_one, METH_VARARGS},
{NULL, NULL}
};

5、创建module的信息,包括了python调用时的模块名、可调用的函数集(就是上一步定义的Methods)等信息

static struct PyModuleDef cModule = {
PyModuleDef_HEAD_INIT,
"Test", /*module name*/
"", /* module documentation, may be NULL */
-, /* size of per-interpreter state of the module, or -1 if the module keeps state in global variables. */
Methods
};

6、module初始化

 PyMODINIT_FUNC PyInit_Test(void){ return PyModule_Create(&cModule);}

7、写一个setup.py脚本,使用distutils包作为包构建安装的工具

from distutils.core import setup, Extension
module1 = Extension('Test', sources = ['add.c'])
setup (name = 'Test',
version = '1.0',
description = 'This is a demo package',
ext_modules = [module1])

8、调用setup.py,python setup.py build可以编译代码,python setup.py install可以编译代码并直接将包放入当前python环境的包的路径以供调用。

非常需要注意的是,python 3.5版本以后,windows平台下python的C/C++扩展不再支持gcc的编译,并强制要求使用msvc进行编译

所以python setup.py build编译出来的结果无法正常使用,需使用

python setup.py build --compiler msvc

当需要安装时,则

python setup.py build --compiler msvc install

关于此情况的参考:

https://stackoverflow.com/questions/16737260/how-to-tell-distutils-to-use-gcc

https://stackoverflow.com/questions/3297254/how-to-use-mingws-gcc-compiler-when-installing-python-package-using-pip

9、测试安装好的C扩展

import Test as t
x = 1
print(t.add_one(x))

附C文件完整代码

#include <Python.h>

int add_one(int a){
return a + ;
} static PyObject * py_add_one(PyObject *self, PyObject *args){
int num;
if (!PyArg_ParseTuple(args, "i", &num)) return NULL;
return PyLong_FromLong(add_one(num));
} static PyMethodDef Methods[] = {
{"add_one", py_add_one, METH_VARARGS},
{NULL, NULL}
}; static struct PyModuleDef cModule = {
PyModuleDef_HEAD_INIT,
"Test", /*module name*/
"", /* module documentation, may be NULL */
-, /* size of per-interpreter state of the module, or -1 if the module keeps state in global variables. */
Methods
}; PyMODINIT_FUNC PyInit_Test(void){ return PyModule_Create(&cModule);}

https://segmentfault.com/a/1190000000479951

最新文章

  1. 仅用aspx文件实现Ajax调用后台cs程序。(实例)
  2. Linux下PHP安装oci8扩展
  3. Codeforces 719E [斐波那契区间操作][矩阵快速幂][线段树区间更新]
  4. YTU 2616: A代码完善--简易二元运算
  5. Magento网站如何添加一个可配置产品
  6. maven在mac上的入门使用
  7. 原生js-拉勾网首页效果
  8. Windbg 32位版本和64位版本的选择
  9. java 子类与父类继承关系
  10. 更改pandas dataframe 列的顺序
  11. FastDfs上传图片
  12. AOP统一处理Web请求日志
  13. Eclipse Todo Tasks 任务试图
  14. 用vi编辑文件
  15. Nginx——location匹配与在配置中的优先级
  16. Linux基础命令---添加用户useradd
  17. POJ 2135 Farm Tour (网络流,最小费用最大流)
  18. Summary: Depth-first Search(DFS)
  19. 51nod 1693 水群(神奇的最短路!)
  20. the django travel(two)分页

热门文章

  1. Python之configparser配置文件的读取
  2. 吴裕雄--天生自然python学习笔记:Python3 模块
  3. Junit 单元测试在 intelliJ IDEA 中的安装
  4. 吴裕雄--天生自然 R语言开发学习:方差分析(续一)
  5. 初等数论-Base-2(扩展欧几里得算法,同余,线性同余方程,(附:裴蜀定理的证明))
  6. mysql表关系
  7. Laravel 队列使用
  8. 添砖加瓦:简述ELK部署
  9. NERDTree快捷键
  10. 网络编程01 &middot; 艺