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

python的C扩展调用,使用原生的python-C-Api的更多相关文章

  1. python获取文件扩展名的方法(转)

    主要介绍了python获取文件扩展名的方法,涉及Python针对文件路径的相关操作技巧.具体实现方法如下: 1 2 3 4 import os.path def file_extension(path ...

  2. python获取文件扩展名的方法

    主要介绍了python获取文件扩展名的方法,涉及Python针对文件路径的相关操作技巧 import os.path def file_extension(path): ] print file_ex ...

  3. python使用C扩展

    CPython还为开发者实现了一个有趣的特性,使用Python可以轻松调用C代码 开发者有三种方法可以在自己的Python代码中来调用C编写的函数-ctypes,SWIG,Python/C API.每 ...

  4. Python与Javascript相互调用超详细讲解(2022年1月最新)(三)基本原理Part 3 - 通过C/C++联通

    目录 TL; DR python调javascript javascript调python 原理 基于Node.js的javascript调用python 从Node调用python函数 V8 嵌入P ...

  5. python与c互相调用

    虽然python开发效率很高,但作为脚本语言,其性能不高,所以为了兼顾开发效率和性能,通常把性能要求高的模块用c或c++来实现或者在c或c++中运行python脚本来处理逻辑,前者通常是python中 ...

  6. paip.java c# .net php python调用c++ c dll so windows api 总结

    paip.java c# .net  php python调用c++ c dll so windows api 总结 作者Attilax  艾龙,  EMAIL:1466519819@qq.com 来 ...

  7. Python 的 JPype 模块调用 Jar 包

    背景与需求 最近学习并安装使用了HttpRunner框架去尝试做接口测试,并有后续在公司推广的打算. HttpRunner由Python开发,调用接口时需要依赖Python:而大多数公司的扩展工具包使 ...

  8. [转] C++ 和 python之间的互相调用

    转载自:https://www.cnblogs.com/apexchu/p/5015961.html 一.Python调用C/C++ 1.Python调用C动态链接库 Python调用C库比较简单,不 ...

  9. (转载)Python 的 JPype 模块调用 Jar 包

    Python 的 JPype 模块调用 Jar 包 背景与需求 最近学习并安装使用了HttpRunner框架去尝试做接口测试,并有后续在公司推广的打算. HttpRunner由Python开发,调用接 ...

随机推荐

  1. Python之configparser配置文件的读取

    配置文件名 config.ini 文件内容: [linux] ip:10.0.13.26 port:22 username:root password:W2ynE6b58wheeFho [mysql] ...

  2. SpringBoot打印MyBatis sql日志输出

    SpringBoot打印MyBatis sql日志输出 默认情况下mybatis是不开启SQL日志输出,需要手动配置 方法一:(在mybatis整合在springboot框架的情况下) 只需要在配置文 ...

  3. <luogu1347>排序

    本来打算当打了个拓扑的板子 后来发现并不只是个板子 差不多 管他呢 #include<cstdio> #include<cstring> #include<iostrea ...

  4. python反转链表和成对反转

    https://www.cnblogs.com/tianqizhi/p/9673894.html https://blog.csdn.net/weixin_34168700/article/detai ...

  5. hexo博客的学习笔记

    这篇文章主要的作用是作为 .md文件打开,内部的格式为一个初学者对hexo以及markdown语法运用的笔记 1.Hexo的写文格式 最开始为文章的属性部分,以三横杠-开始,-结束.里面记录了文章的标 ...

  6. windowserver 2012安装openssh

    下载https://github.com/PowerShell/Win32-OpenSSH/releases解压放到C:\Program Files\OpenSSH-Win64 进入到C:\Progr ...

  7. 让git push命令不再需要密码

    最近利用jekyll写博客,为的就是博客管理方便,但是在上传博客的时候使用git push命令每次都得输入github帐号和密码特别的不方便,于是就搜了一下. 在这篇文章里提到,GitHub获得远程库 ...

  8. sms短信服务

    短信服务是app,电商类应用的基础功能.典型场景有: 用户注册,发送验证码 用户找回验证,发送验证码 用户账户异常,发送提示 用户账户变化,通知用户 短信服务开发有几个注意点: 供应商选型 短信模板 ...

  9. 树的三种DFS策略(前序、中序、后序)遍历

    之前刷leetcode的时候,知道求排列组合都需要深度优先搜索(DFS), 那么前序.中序.后序遍历是什么鬼,一直傻傻的分不清楚.直到后来才知道,原来它们只是DFS的三种不同策略. N = Node( ...

  10. yii框架通过控制台命令创建定时任务

    假设Yii项目路径为 /home/apps 1. 创建文件 /home/apps/web/protected/commands/console.php $yii = '/home/apps/frame ...