robot
最新文章(10)
Mqskit 和其它相關工具
CPython 的 GC 二、三事
寫 Mecurial Extension 是件快樂的事!
Mozilla 台灣辨公室徵人啟事
關於 Apple 的兩項專利
core dump 之前的 frame
怎麼發出 beep 聲?
先承認你要找的是奴才吧!
程式碼要清的多乾淨?
FreeBSD 的 Thread-Local Storage 實作
首頁
新編
最新留言
Entries RSS
重要關鍵字(10)
coding (122)
Python (93)
FreeBSD (71)
WEB (61)
URL (48)
hardware (46)
javascript (36)
Linux (34)
blog (30)
C++ (16)
所有關鍵字
新增 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: