C++扩展python modules

  • 函数详情

    #<Python.h>
    C语言扩展python
    1. PyObject 所有的python扩展类型对象

      <font color=#7093DB>描述所有python对象再C中的对象</font>

    1. PyMethodDef 描述扩展type方法的struct

      <font color=#7093DB>自定义Python 方法</font>

      C 类型 含义
      ml_name char * name of the method
      ml_meth PyCFunction pointer to the C implementation
      ml_flags 整型 flag bits indicating how the call should be constructed
      ml_doc char * points to the contents of the docstring

      <font color=#7093DB>ml_flags: 可选值有 METH_VARARGSMETH_VARARGS | METH_KEYWORDS,如果单独使用 METH_VARARGS ,函数会接受Python tuple格式的参数,并使用 PyArg_ParseTuple() 解析。METH_KEYWORDS 表示接受关键字参数,这种情况下C函数需要接受第三个 PyObject * 对象,表示字典参数,使用 PyArg_ParseTupleAndKeywords() 解析参数。</font>

    2. PyMODINIT_FUNC 定义返回值为void的python moudle

      <font color=#7093DB>声明函数的返回值为void, 在python3中返回PyObject * ,声明为python module</font>

    3. PyArg_ParseTuple

    int PyArg_ParseTuple(PyObject *arg, char *format, ...)
    arg:<font color=green>元组,代表python的参数列表</font>
    format:<font color=green>格式化字符串</font>

    <font color=#7093DB> 解析一个函数的参数,表达式中的参数按参数位置顺序存入局部变量中。成功返回true;失败返回false并且引发相应的异常 </font>

    示例:
       int ok;
        int i, j;
        long k, l;
        char *s;
        int size;
        ok = PyArg_ParseTuple(args, "");/* No arguments */
            /* Python call: f() */
        ok = PyArg_ParseTuple(args, "s",&s); /* A string */
            /* Possible Python call: f('whoops!')*/
        ok = PyArg_ParseTuple(args,"lls", &k, &l, &s); /* Two longs and a string */
            /* Possible Python call: f(1, 2,'three') */
        ok = PyArg_ParseTuple(args,"(ii)s#", &i, &j, &s, &size);
            /* A pair of ints and a string, whosesize is also returned */
            /* Possible Python call: f((1, 2),'three') */
        {
            char *file;
            char *mode = "r";
            int bufsize = 0;
            ok = PyArg_ParseTuple(args,"s|si", &file, &mode, &bufsize);
            /* A string, and optionally anotherstring and an integer */
            /* Possible Python calls:
               f('spam')
               f('spam', 'w')
               f('spam', 'wb', 100000) */
        }
    
        {
            int left, top, right, bottom, h, v;
            ok = PyArg_ParseTuple(args,"((ii)(ii))(ii)",
                     &left, &top,&right, &bottom, &h, &v);
            /* A rectangle and a point */
            /* Possible Python call:
               f(((0, 0), (400, 300)), (10, 10)) */
        }
    
        {
            Py_complex c;
            ok = PyArg_ParseTuple(args,"D:myfunction", &c);
            /* a complex, also providing a functionname for errors */
            /* Possible Python call:myfunction(1+2j) */
    
        }
    
    1. Py_BuildValue 创建python对象为C对象
      PyObject* Py_BuildValue( const char *format, ...)
      format:<font color=green>格式化字符串</font>

    2. PyInit_sample 模块初始化函数

      <font color=#7093DB>该模块第一次被导入时执行</font>

    3. Py_InitModule (python3, PyModule_Create) 创建python modlue
      PyObject* Py_InitModule(char *name, PyMethodDef *methods)
      name:<font color=green>module的名称</font>
      methods:<font color=green>module的方法</font>

      <font color=#7093DB>根据给定的name和function,创建新的python modlue</font>

    4. PyLong_FromLong 转化C long为python 对象
      PyObject* PyLong_FromLong(long v)
      v:<font color=green>C long</font>

    5. PyLong_AsLong 转化python的long对象为C long
      long PyLong_AsLong(PyObject *pylong)
      pylong:<font color=green>python long对象</font>

    6. Py_None Python None 对象

      <font color=#7093DB> Python None 对象,表示缺乏值。 </font>

    C语言调用python
    1. PyImport_AppendInittab 增加一个python build-in module
      int PyImport_AppendInittab(const char *name, void (*initfunc)(void))
      name:<font color=green>模块名称</font>
      initfunc:<font color=green>模块init dunction</font>

      <font color=#7093DB> 调用python sys.module,添加一个自定module</font>

    2. Py_Initialize 初始化python模块
      void Py_Initialize()

      <font color=#7093DB>初始化python解释器,须在调用所有Python/C API之前调用 </font>

    3. Py_Finalize 释放模块
      void Py_Finalize()

      <font color=#7093DB>释放所有初始化和调用的Python/C API的资源 </font>

    4. PyImport_ImportModule 加载python模块
      PyObject* PyImport_ImportModule(const char *name)
      name:<font color=green>需要导入modlue name</font>

    5. PyObject_GetAttrString 获取对象值
      PyObject* PyObject_GetAttrString(PyObject *o, const char *attr_name)
      o:<font color=green>python对象</font>
      attr_name:<font color=green>调用对象name</font>

      <font color=#7093DB>获取o的attr_name的值,o.attr_name</font>

    6. PyEval_CallObject 调用函数

    PyObject* PyEval_CallObject(PyObject* pfunc, PyObject*pargs)
    pfunc:<font color=green>调用函数</font>
    pargs:<font color=green>函数参数列表</font>

    <font color=#7093DB>PyObject_CallObject() 返回Python对象指针,这也是Python函数的返回值。 PyObject_CallObject() 是一个对其参数 “引用计数无关” 的函数。例子中新的元组创建用于参数列表,并且在 PyObject_CallObject() 之后立即使用了 Py_DECREF() 。</font>

    <font color=#7093DB>PyEval_CallObject() 的返回值总是“新”的:要么是一个新建的对象;要么是已有对象,但增加了引用计数。所以除非你想把结果保存在全局变量中,你需要对这个值使用 Py_DECREF(),即使你对里面的内容(特别!)不感兴趣。</font>

    1. PyList_New 创建python列表的C对象
      PyObject* PyList_New( Py_ssize_t len)
      len: <font color=green>列表长度</font>

    2. PyList_SetItem 给列表添加元素
      int PyList_SetItem( PyObject *list, Py_ssize_t index, PyObject *item)
      list: <font color=green>python list的C对象</font>
      index: <font color=green>索引位置</font>
      item: <font color=green>列表值</font>

    3. PyList_GetItem 获取列表的值
      PyObject* PyList_GetItem( PyObject *list, Py_ssize_t index)
      list:<font color=green>python list的C对象</font>
      index:<font color=green>索引位置</font>

    4. Py_CLEAR & Py_DECREF 释放资源
      void Py_CLEAR( PyObject *o)
      void Py_DECREF( PyObject *o)
      o: <font color=green>Python的C对象</font>

      <font color=#7093DB>Py_CLEAR的参数可以为NULL</font>

    5. PyObject_CallObject 调用python函数
      PyObject* PyObject_CallObject( PyObject *callable_object, PyObject *args)
      callable_object: <font color=green>python的函数对象</font>
      args: <font color=green>参数列表(元组)</font>

    6. PyObject_CallFunction 调用python函数
      PyObject* PyObject_CallFunction( PyObject *callable, char *format, ...)
      callable:<font color=green>python的函数对象</font>
      format:<font color=green>参数类型(格式化字符串)</font>

    7. PyObject_CallMethod 调用python函数

    PyObject* PyObject_CallMethod(PyObject o*, char method, char **format, ...)

    o:<font color=green>python module的C对象</font>
    method:<font color=green>函数名</font>
    format:<font color=green>格式化字符串,函数参数</font>
    
    1. PyArg_ParseTuple 获取扩展函数参数
      int PyArg_ParseTuple(PyObject *arg, char *format, ...)
      args: <font color=green>python的函数对象</font>
      format: <font color=green>参数列表(元组)</font>

      <font color=#7093DB >解析一个函数的参数,表达式中的参数按参数位置顺序存入局部变量中 </font>

    2. PyRun_SimpleString 调用python源码code

    int PyRun_SimpleString(const char **command*)
    command:<font color=green>python 调用源码code</font>

    Format格式化字符串
    • s (string or Unicode) [const char *]

    <font color=green>转化python的字符串或者Unicode对象为C的char指针</font>

    • s# (string, Unicode or any read buffer compatible object) [const char *, int (or Py_ssize_t, see below)

    <font color=green> 转化python的字符串或者Unicode对象为两个C变量,一个是字符指针,另一个是字符串长度</font>

    • s* (string, Unicode, or any buffer compatible object) [Py_buffer]

    <font color=green>同s#</font>

    • z (string, Unicode or None) [const char *]

    <font color=green>和s类似,字符串可以为None</font>

    • z# (string, Unicode, None or any read buffer compatible object) [const char *, int]

    <font color=green> 同s#</font>

    • z* (string, Unicode, None or any buffer compatible object) [Py_buffer]

    <font color=green>同s* </font>

    • u (Unicode) [Py_UNICODE *]

    <font color=green>转化python Unicode为C 16-bit Unicode指针</font>

    • u# (Unicode) [Py_UNICODE *, int]

    <font color=green>转化python Unicode为两个C对象,一个为C 16-bit Unicode指针,另一个是长度</font>

    • es (string, Unicode or character buffer compatible object) [const char *encoding, char **buffer]

    <font color=green>转化python encoding Unicode为C encoding指针,只对encoded的数据生效</font>

    • et (string, Unicode or character buffer compatible object) [const char *encoding, char **buffer]

    <font color=green>与es类似,只适用于8-bits字符串</font>

    • es# (string, Unicode or character buffer compatible object) [const char *encoding, char **buffer, int *buffer_length]

    <font color=green>类似s#,输出字符串长度</font>

    • et# (string, Unicode or character buffer compatible object) [const char *encoding, char **buffer, int *buffer_length]

    <font color=green>同es#</font>

    • b (integer) [unsigned char]

    <font color=green> 转化非负的Python整型为无符号的微整型,存储在一个C unsigned char 类型中 </font>

    • B (integer) [unsigned char]

    <font color=green> 将一个Python整型转化成一个微整型并不检查溢出问题,存储在一个C unsigned char 类型中 </font>

    • h (integer) [short int]

    <font color=green> 将一个Python整型转化成一个C short int 短整型 </font>

    • H (integer) [unsigned short int]

    <font color=green> 将一个Python整型转化成一个C unsigned short int 无符号短整型,并不检查溢出问题</font>

    • i (integer) [int]

    <font color=green> 将一个Python整型转化成一个C int 整型</font>

    • I (integer) [unsigned int]

    <font color=green> 将一个Python整型转化成一个C unsigned int 无符号整型,并不检查溢出问题 </font>

    • l (integer) [long int]

    <font color=green> 将一个Python整型转化成一个C long int 长整型 </font>

    • k (integer) [unsigned long]

    <font color=green>转化python的int为一个C unsigned long </font>

    • L (integer) [PY_LONG_LONG]

    <font color=green>转化python的int为一个C long long</font>

    • K (integer) [unsigned PY_LONG_LONG]

    <font color=green>转化python的int为一个C unsigned long long</font>

    • n (integer) [Py_ssize_t]

    <font color=green>转化python的int为一个C Py_ssize_t </font>

    • c (string of length 1) [char]

    <font color=green>转化python的长度为1的字符串为C char</font>

    • f (float) [float]

    <font color=green>转化python的float为一个C float</font>

    • d (float) [double]

    <font color=green> 将一个Python浮点数转化成一个C double 双精度浮点数 </font>

    • D (complex) [Py_complex]

    <font color=green>将一个Python复数类型转化成一个C Py_complex Python复数类型</font>

    • O (object) [PyObject *]

    <font color=green>>将一个Python对象存入一个C指针</font>

    • O! (object) [typeobject, PyObject *]

    <font color=green>将一个Python对象存入一个C指针。和 O 类似,但是需要两个C参数:第一个是Python类型对象的地址,第二个是存储对象指针的C变量( PyObject* 变量)的地址。如果Python对象类型不对,会抛出 TypeError 异常</font>

    • O& (object) [converter, anything]

    <font color=green>转化一个python对象,通过一个converter函数转化C对象</font>

    • S (string) [PyStringObject *]

    <font color=green>和O类似,但是必须是python的string对象</font>

    • U (Unicode string) [PyUnicodeObject *]

    <font color=green>和O类似,但是必须是python的 Unicode string对象</font>

    • t# (read-only character buffer) [char *, int]

    <font color=green>和s#类似,但是必须是python的只读buffer</font>

    • w (read-write character buffer) [char *]

    <font color=green>和s类似,但是必须是所有python 读写buffer接口</font>

    • w# (read-write character buffer) [char *, Py_ssize_t]

    <font color=green>和s#类似,但是必须是所有python 读写buffer接口</font></font>

    • w* (read-write byte-oriented buffer) [Py_buffer]

    <font color=green>和s*类似</font>

    • (items) (tuple) [matching-items]

    <font color=green> 对象必须是Python序列,它的长度是 items 中格式单元的数量。C参数必须对应 items 中每一个独立的格式单元。序列中的格式单元可能有嵌套 </font>

    • |

    <font color=green>参数可选</font>

    • :

    <font color=green>格式单元的列表结束标志;冒号后的字符串被用来作为错误消息中的函数名(PyArg_ParseTuple() 函数引发的“关联值”异常)</font>

    • ;

    <font color=green>格式单元的列表结束标志;分号后的字符串被用来作为错误消息取代默认的错误消息。 : 和 ; 相互排斥</font>

  • 扩展python示例

    1. C++代码,great_module.c
    #include <Python.h>
    
    int great_sum(int a,int b) {
        return a + b;
    }
    
    void great_hello(){
        printf("Hello world!");
    }
    
    static PyObject * _great_sum(PyObject *self, PyObject *args)
    {
        int _a,_b;
        int res;
    
        if (!PyArg_ParseTuple(args, "ii", &_a, &_b))
            return NULL;
        res = great_sum(_a, _b);
        return PyLong_FromLong(res);
    }
    
    static PyObject * _great_hello(PyObject *self, PyObject *args)
    {
        if (!PyArg_ParseTuple(args, ""))
            return NULL;
        great_hello();
        return Py_None;
    }
    
    static PyMethodDef GreateModuleMethods[] = { 
        {"hello", _great_hello, METH_VARARGS, "Print the 'Hello World!'"},
        {"sum", _great_sum, METH_VARARGS, "sum(int a,int b)"},
        {NULL, NULL, 0, NULL}
    };
    PyMODINIT_FUNC initgreat_module(void) {
        (void) Py_InitModule("great_module", GreateModuleMethods);
    }
    
    1. python setup

      #!/usr/bin/env python
      #-- coding:utf-8 -*-
      
      
      from setuptools import setup, Extension
      
      
      hello_world = Extension('great_module', sources=["great_module.c"])
      setup(name='great_module',
            version='1.0',
            description='This is a package for my first module.',    
            ext_modules=[hello_world]
            ) 
      
    2. c++调用python, build_in_module.c

      #include "great_module.c"
      
      int main()
      {
          PyImport_AppendInittab("great_module", &initgreat_module);
          Py_InitializeEx(0);        
          PyRun_SimpleString("import great_module");
          PyRun_SimpleString("great_module.hello()");
          PyRun_SimpleString("s = great_module.sum(1,2)");
          PyRun_SimpleString("print s");
          Py_Finalize();
          return 0;
      }
      

      build_in_import_module.cc

      #include "great_module.c"
      
      int main()
      {
          PyObject * pModule = NULL;
          PyObject * pFunc = NULL;
          PyObject * pReturn = NULL;
      
          PyImport_AppendInittab("great_module", &initgreat_module);
          Py_InitializeEx(0);
      
          pModule =  PyImport_ImportModule("great_module");
          pFunc = PyObject_GetAttrString(pModule, "hello");
          PyObject_CallObject(pFunc,NULL);
          
          int sum;
          pFunc = PyObject_GetAttrString(pModule, "sum");
          pReturn = PyObject_CallObject(pFunc,Py_BuildValue("ii", 1, 2));
          PyArg_Parse(pReturn,"i",&sum);
          printf(": %d",sum);
          printf("\n sum:: %d",PyLong_AsLong(pReturn));
      
          pReturn = PyObject_CallMethod(pModule,"sum","(i,i)",10,20);
          printf("\n sum:: %d",PyLong_AsLong(pReturn));
          pReturn = PyObject_CallFunction(pFunc, "ii",3,2);
          printf("\n sum:: %d",PyLong_AsLong(pReturn));
          
          Py_DECREF(pReturn);
      
          Py_Finalize();
          return 0;
      }
      
  • 文档查询

    https://docs.python.org/zh-cn/3.7/genindex-P.html
    
  • 编译gcc

    gcc build_in_module.c -I/usr/include/python2.7 -lpython2.7
    
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,657评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,662评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,143评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,732评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,837评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,036评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,126评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,868评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,315评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,641评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,773评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,470评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,126评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,859评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,095评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,584评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,676评论 2 351

推荐阅读更多精彩内容