robot
最新文章(10)
MadButterfly 和 Javascript 合體的威力
Adapt C code for Javascript
OpenVG for Linux/FreeBSD with X
回收 Linux cached memory
公告: 更換 domain name
關於 GCC nested function
GLUT 作為 Embedded System 的 UI 平台
別被 kernel 嚇到了
SVG 加 Gecko 完全攻略
在 OSDC 展示的 Plurk client
首頁
新編
最新留言
Entries RSS
重要關鍵字(10)
coding (120)
Python (93)
FreeBSD (71)
WEB (61)
URL (48)
hardware (46)
雜記 (45)
javascript (36)
Linux (31)
blog (30)
所有關鍵字
新增 URL
為 Embedded Python 擴充 Submodules
by thinker
2 Columns
關鍵字:
Python
coding
$Python$ 有一個很重要的功能,能 embedded 在其它程式裡,以 $Python$ 作為 scripting language ,擴充程式功能。另一方面,主程式也可擴充 $Python$ 的功能,供 module 予 $Python$ script 使用。一般的做法,是使用 $C$/$C++$ 編寫 so 或 dll ,供 $Python$ 載入為 module 。然而,這樣的方式有些麻煩,繞了一圈,不如由主程式直接提供 Embedded $Python$ module ,不經過 so 或 dll 。 == Embedded $Python$ == {{{ #include <stdio.h> #include <stdlib.h> #include <$Python$.h> PyObject *time_mod; PyObject *time_func; PyObject *result; long tm; Py_Initialize(); time_mod = PyImport_ImportModule("time"); if(time_mod == NULL) abort(); time_func = PyObject_GetAttrString(time_mod, "time"); if(time_func == NULL) abort(); result = PyObject_CallObject(time_func, NULL); if(result == NULL) abort(); tm = PyLong_AsLong(result); printf("It is %l seconds since 1970.01.01\n", tm); Py_DECREF(result); Py_DECREF(time_func); Py_DECREF(time_mod); Py_Finalize(); }}} 這一段程式,相當於 {{{ import time tm = time.time() print "It is %d seconds since 1970.01.01\n" % (tm) }}} Embedded $Python$ 的使用方式相當容易,只需使用 $C$/$C++$ 呼叫 Py_Initialize() ,然後呼叫 $Python$ 執行一些動作。例如 load module ,執行 function 等等的。最後呼叫 Py_Finalize() 結束 $Python$ 。 使用 Embedded $Python$ 時,要特別注意 linkname:[reference count] http://docs.python.org/ext/ownershipRules.html ,以維 $Python$ GC 的正常運作。 == 擴充 Module == 主程式為 Embedded $Python$ 擴充 module 很容易,只需在 Py_Initialize() 之後,呼叫 Py_InitModule() 就可以。 {{{ PyObject *hello(PyObject *self) { return PyString_FromString("Hello"); } PyObject *mul(PyObject *self, PyObject *args) { int a, b; if(!PyArg_ParseTuple(args, "ii", &a, &b)) return NULL; return PyInt_FromLong(a * b); } PyMethodDef methods[] = { {"hello", (PyCFunction)hello, METH_NOARGS, "hello document"}, {"mul", (PyCFunction)mul, METH_VARARGS, "mul document"}, { NULL, NULL, 0, NULL} }; .... Py_Initialize() Py_InitModule("mymodule", methods); }}} 此例建立 mymodule 這個 module ,並且提供 hello() 和 mul() 兩個 function 。因為 hello() 並不接受任何參數,所以 methods array 裡,將其定義為 METH_NOARGS 。相對於 hello() , mul() 接受兩個參數,所以定義為 METH_VARARGS ,並且 mul() $C$ function ,也多了一個 args 的 argument 。 $Python$ 將所有的 non-$keyword$ argument 都包裝成一個 tuple ,透過第二個參數傳遞。因此, mul() 使用 PyArg_ParseTuple() 將參數讀出為 a 和 b 兩個 local 變數。 ( linkname:[參考] http://docs.python.org/ext/extending-with-embedding.html ) == 主程式擴充 Submodule == Submodule 也就在別的 package 之下的 module 。例如 sys.path 就是一個 submodule 。 submodule 的問題是,在不知名的原因下, Py_InitModule("foo.boo", methods) 之後, "foo.boo" 是出現在 sys.modules 裡了,但是 foo 這個 module 裡面並沒有 import boo 這個 name ,造成 {{{ from foo import boo }}} 或 {{{ import foo.boo a = foo.boo }}} 無法執行。這一切都是因為 $Python$ 在 import module 時,需要一層接著一層,順著 module 讀取 path 的下一個 module。但因 Py_InitModule("foo.boo", methods) 並不會在 "foo" 的 namespace 裡,將 "boo" 指定為新建立的 "foo.boo" module ,造成 import 時,無法從 foo module 的 namespace 找到 boo 。 為此, programmer 必需自行將 submodule 加入到上一層 module/package 的 namespace 裡。 {{{ PyObject *foo_boo, *foo; foo_boo = Py_InitModule("foo.boo", ...); foo = PyImport_ImportModule("foo"); PyModule_AddObject(foo, "boo", foo_boo); Py_DECREF(foo); }}} 透過 PyModule_AddObject() 將 foo.boo 加入 foo 的 namespace 。如此 $Python$ script 就能順利 import foo.boo 這個 module 了。
最後更新時間: 2007-02-20 01:34:36 CST |
引用
查詢:
COMMENTS: