43

Qt使用C/C++扩展Python内置模块

 4 years ago
source link: https://www.tuicool.com/articles/eQZZziU
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

之前和大家介绍过在C/C++中嵌入 Python ,本次和大家分享下使用 C/C++ 扩展 Python 内置模块的方法。

被扩展出来的新模块可以做两件无法直接在Python中完成的事情:一可以实现新的内置对象类型,二则可以调用 C 库函数和一些其他的系统调用。

使用平台:ubuntu14.04、 python3.5Qt 5.5.1

下面借助Qt创建一个叫 libpy3extendPython 内置模块,它可以做一个简单的加法操作,还可以返回一个自定义的数据类型。调用形式如下:

import libpy3extend

libpy3extend.extend_add(1,99)

ibpy3extend.extend_str()

先使用Qt建一个生成库的工程,之后按照步骤进行操作即可。

1. extend.cpp文件首先是包含所用到的头文件:

#include <iostream>

#include <python3.5/Python.h>

2. 向extend.cpp模块文件中添加 C 函数,该函数在执行 libpy3extend.extend_add(1,99)    时被调用。 C 函数总是有两个参数,通常命名为 selfargs

static PyObject *extend_add(PyObject *self, PyObject *args)

{

(void)(self);

PyObject *pArgs = NULL;


int result = 0;

int arg1 = 0;

int arg2 = 0;


if (!PyArg_ParseTuple(args, "ii",&arg1,&arg2))

{

std::cerr << "parameters error" << std::endl;

Py_INCREF(Py_None);

pArgs = Py_None;

}

else

{

result = arg1 + arg2;

pArgs = Py_BuildValue("i", result);

}


return pArgs;

}

args参数是一个元组对象,使用 PyArg_ParseTuple() 函数来解析,解析规则可参考 python 文档

https://docs.python.org/3/c-api/arg.html#arg-parsing

3. 创建模块方法表并在表中列出函数名称和地址。

static PyMethodDef extendMethods[] = {

//extend add

{"extend_add", extend_add, METH_VARARGS, NULL},

{"extend_str", extend_str, METH_VARARGS, NULL},

{NULL, NULL, 0, NULL}

};

METH_VARARGS 表示该函数希望参数传递为元组数据以使用 PyArg_ParseTuple() 函数来解析。

4. 在模块定义结构中引用方法表

static struct PyModuleDef extendMoudle =

{

PyModuleDef_HEAD_INIT,

"py3extend", /* 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. */

extendMethods,


NULL,

NULL,

NULL,

NULL

};

5. 将刚才定义的结构传递给模块初始化函数中的解释器。

注意:必须命名初始化函数 PyInit_name() ,其中 name 是模块的名称 。我这里模块   名称是 py3extend ,但是由于生成的是库文件,会自动加上 lib 前缀,所以这  里模块名称是 lib py3extend ,不是该名称会报

ImportError: dynamic module does not define module export function      (PyInit_libpy3extend)

这个错误。

PyMODINIT_FUNC PyInit_libpy3extend(void)

{

//to use thread in extend moudle

// if (!PyEval_ThreadsInitialized()) {

// PyEval_InitThreads();

// }


return PyModule_Create(&extendMoudle);

}

到这里就可以借助Qt生成库文件了,如果不知道怎么使用 Qt 生成库文件可以参考Qt创建共享库该文章。

接下来是如何使用库文件。将库文件与python测试文件放到同一目录下,即可运行测试。如图:

f2Izyq3.jpg!web

如需要完成工程可在公众号后台留言。

欢迎交流:

eIZJ3iQ.jpg!web


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK