Extending Python with C\C++ 实践问题
来源:互联网 发布:数据挖掘工程师面试题 编辑:程序博客网 时间:2024/05/16 17:19
python doc:Extending Python
根据上面的内容,可编写如下程序:
#include <Python.h>static PyObject *spam_system(PyObject *self, PyObject *args){ const char *command; int sts; if (!PyArg_ParseTuple(args, "s", &command)) return NULL; sts = system(command); return Py_BuildValue("i", sts);}static PyMethodDef SpamMethods[] = { {"system", spam_system, METH_VARARGS,"Execute a shell command."}, {NULL, NULL, 0, NULL}};PyMODINIT_FUNCinitspam(void){ Py_InitModule("spam", SpamMethods);}
利用codeblocks新建工程,编译dll, 具体操作步骤可参考Python之美[从菜鸟到高手]。通过这篇文章,我成功在python里调用到了spam.system(‘ls -s’)。
1 标准异常
阅读python官方文档Extending Python with C\C++后,第二小节是关于异常的,我试着在上面代码中加入异常的语句,如下:
#include <Python.h>static PyObject *spam_system(PyObject *self, PyObject *args){ const char *command; int sts; if (!PyArg_ParseTuple(args, "s", &command)) return NULL; sts = system(command); if (sts > 0) //添加异常,如果系统没有传入的命令,返回值不为0 { //这里的异常PyExc_ArithmeticError是我随便选的预定义异常对象 PyErr_SetString(PyExc_ArithmeticError, "something is wrong"); return NULL; } return Py_BuildValue("i", sts);}static PyMethodDef SpamMethods[] = { {"system", spam_system, METH_VARARGS,"Execute a shell command."}, {NULL, NULL, 0, NULL}};PyMODINIT_FUNCinitspam(void){ Py_InitModule("spam", SpamMethods);}
编译出错,出现错误:undefined reference to _imp__PyErr_SetString, 缺少库文件,需要把libpython26.a添加到codeblocks的链接库中,和python26.lib一块。然后就可以编译成功了。其中的PyExc_ArithmeticError是预定义的一些标准异常,可参考标准异常。编译成功后,在python中调用如下:
>>>import spam>>> spam.system('lll')Traceback (most recent call last): File "<pyshell#12>", line 1, in <module> spam.system('lll')ArithmeticError: something is wrong>>> spam.system('ls -s')0>>>
2 自定义异常
下面就是自定义异常:
#include <Python.h>static PyObject *SpamError;static PyObject *spam_system(PyObject *self, PyObject *args){ const char *command; int sts; if (!PyArg_ParseTuple(args, "s", &command)) return NULL; sts = system(command); if (sts > 0) { PyErr_SetString(SpamError, "something is wrong"); return NULL; } return Py_BuildValue("i", sts);}static PyMethodDef SpamMethods[] = { {"system", spam_system, METH_VARARGS,"Execute a shell command."}, {NULL, NULL, 0, NULL}};PyMODINIT_FUNC initspam(void){ PyObject *m; m = Py_InitModule("spam", SpamMethods); if (m == NULL) return; SpamError = PyErr_NewException("spam.error111", NULL, NULL); Py_INCREF(SpamError); PyModule_AddObject(m, "error222", SpamError);}
编译后,在python中调用,结果:
>>> import spam>>> spam.system('lll')Traceback (most recent call last): File "<pyshell#15>", line 1, in <module> spam.system('lll')error111: something is wrong>>>
异常的名字为error111,异常信息something is wrong。当在python IDLE中导入spam,可发现:
>>> spam.error222<class 'spam.error111'>>>>
spam.error111是异常对象SpamError所属异常类的名字,PyModule_AddObject则把对象SpamError添加到模块m(spam模块)的属性字典中,key是error222。
3 其它
1. PyErr_Occurred()
PyErr_Occurred 用来判断是否产生了一个异常,如果没有,返回NULL,PyErr_Occurred() == NULL 返回True;如果有异常,该函数返回最近的一个异常对象,可使用PyErr_ExceptionMatches()进行对比:
if (sts > 0) { PyErr_SetString(SpamError, "something is wrong"); if(PyErr_ExceptionMatches(SpamError)) { PyErr_SetString(PyExc_ArithmeticError, "PyExc_ArithmeticError"); return NULL; } return NULL; } return Py_BuildValue("i", sts);
用上面代码替换第2节对应位置,编译后,在python执行:
>>> import spam>>> spam.system('lll')Traceback (most recent call last): File "<pyshell#19>", line 1, in <module> spam.system('lll')ArithmeticError: PyExc_ArithmeticError>>>
返回ArithmeticError而不是SpamError。
2. PyErr_Clear()
如果要忽略不处理异常,可调用PyErr_Clear():
if (sts > 0) { PyErr_SetString(SpamError, "something is wrong"); PyErr_Clear(); return NULL; } return Py_BuildValue("i", sts);
编译后,python调用:
>>> import spam>>> spam.system('lll')Traceback (most recent call last): File "<pyshell#21>", line 1, in <module> spam.system('lll')SystemError: error return without exception set>>>
上面这个异常,可能是return NULL造成的,前面的异常被忽略了。
3. PyArg_ParseTuple()
这个函数是用来解析元组参数的。前面的代码部分:
if (!PyArg_ParseTuple(args, "s", &command)) return NULL;
“s”表示传入一个字符串参数,即python调用为:
>>>spam.system('ls -s')
而如果修改格式字符串:
if (!PyArg_ParseTuple(args, "(s)", &command)) return NULL;
就表示传入一个元组参数,即python调用为:
>>> spam.system(('ls -s',))0>>>
然后可以解析元组的多个参数,修改C代码如下:
static PyObject *spam_system(PyObject *self, PyObject *args){ const char *command1; const char *command2; int sts1, sts2; if (!PyArg_ParseTuple(args, "(ss)", &command1, &command2)) return NULL; sts1 = system(command1); sts2 = system(command2); if (sts1 > 0) { PyErr_SetString(SpamError, "something is wrong"); PyErr_Clear(); return NULL; } return Py_BuildValue("(ii)", sts1, sts2);}
编译后,python调用如下:
>>> spam.system(('ls -s', 'ls -s'))(0, 0)>>>
返回值为一个元组,对应每一个命令的返回值。s或者i分别表示字符串和整数,具体可参考Python官方文档参数解析及值的构造,其中包含了各种类型的格式化字符。
继续实践,字符串和整数的:
const char *command1; const char *command2; int sts1, sts2, temp; temp = 0; if (!PyArg_ParseTuple(args, "(ssi)", &command1, &command2, &temp)) return NULL; sts1 = system(command1); sts2 = system(command2); printf("%d\n", temp); return Py_BuildValue("(iii)", sts1, sts2, temp);
python调用为:
>>> import spam>>> spam.system(('ls -s', 'ls -s', 4))(0, 0, 4)>>>
注意:PyArg_ParseTuple()的后面的参数,都是一些地址!
4. 类、对象、方法、属性
未完,待续
- Extending Python with C\C++ 实践问题
- 编写Python扩展(Extending Python with C or C++)
- 用C/C++扩展Python(Extending Python with C or C++)
- 用C/C++扩展Python(Extending Python with C or C++)
- Python的点点滴滴(C extending)
- python extending with c++
- Python的点点滴滴(Callback From C Extending)
- [ Extending Lua with c/c++ ] & [ Embedding Lua in c/c++ ]
- C Extending or ctypes in pyinotify
- Extending maya with C#
- 背包问题(c/python)
- Extending Lua to C using the LuaJIT FFI library
- LeetCode 11 Container With Most Water (C,C++,Java,Python)
- Extending WCF with Customer Behaviors
- C 语言程序设计实践 8.2 W.C之十个问题
- Python的C扩展问题
- C++/python解决汉诺塔问题
- Linux file system events with C, Python and Ruby
- Struts中使用ajax
- HDU1907 John 【博弈】
- 协方差与协方差矩阵
- stretchableImageWithLeftCapWidth ios支持.9
- java异步发送邮件
- Extending Python with C\C++ 实践问题
- 分布式服务框架远程服务通讯简单实现
- tomcat配置cgi
- android学习之(1)----开发环境搭建
- 角点检测和匹配之Harris与FAST角点检测
- 【tcp-ip学习笔记】关于IP协议层、IP地址
- WPF圆角透明无边框窗体
- An Introduction to Interactive Programming in Python (Part 2) -- week 8
- Android中View not attached to window manager错误,android.view.WindowLeaked的解决方案