您好,登錄后才能下訂單哦!
本文檔適用于希望使用基于SylixOS進行Python擴展庫開發的用戶。
Python是一門面向對象的解釋型的腳本語言,Python具有豐富和強大的庫。它常被昵稱為膠水語言,能夠把用其他語言制作的各種模塊(尤其是C/C++)很輕松地聯結在一起。常見的一種應用情形是,使用Python快速生成程序的原型(有時甚至是程序的最終界面),然后對其中有特別要求的部分,用更合適的語言改寫,比如3D游戲中的圖形渲染模塊,性能要求特別高,就可以用C/C++重寫,而后封裝為Python可以調用的擴展類庫。
目前SylixOS支持的Python為3.6.4版本,支持絕大多數內建庫,但并未移植擴展庫。
可擴展性是Python的一大特色,Python的擴展庫可以基于Python語言開發,也可通過C、JAVA等語言進行開發。
本文將介紹如何使用RealEvo-IDE開發C語言版本的SylixOS Python擴展庫。C語言版本Python擴展庫開發有以下兩種方式。
SylixOS下的Python支持ctypes內建模塊。此模塊的CDLL方法會調用SylixOS操作系統的dlopen()函數,從而導入用戶開發的C/C++動態庫。
編寫簡單的動態庫lib_demo,代碼如程序清單 3.1所示。
程序清單 3.1 動態庫demo
#include <stdio.h>
void lib_func (void)
{
printf("lib_func call!\n");
}
void hello (void)
{
printf("Hello SylixOS!\n");
}
int fact(int n)
{
if (n <= 1)
return 1;
else
return n * fact(n - 1);
}
將lib_demo編譯上傳至目標設備中。新建一個Python腳本test.py,使用VI編輯器編輯python腳本,內容如下:
import ctypes
demo=ctypes.CDLL("/lib/lib_demo.so")
print("-------------")
demo.lib_func()
print("-------------")
demo.hello()
print("-------------")
print(demo.fact(10))
print("-------------")
保存后執行“python test.py”,結果如圖 3.1 所示。
圖 3.1 python腳本執行結果
腳本執行結果顯示,動態庫內的函數被成功調用。
除了使用ctypes直接導入SylixOS動態庫外,python本身也提供自定義擴展庫的模板。通過模板封裝的C/C++動態庫,可以直接使用python的“import”方法導入模塊。
依然以lib_demo為例,首先需要添加所需頭文件的路徑。頭文件在SylixOS的/lib/python3/include目錄下提供,可自行拷貝至開發的動態庫目錄下。環境配置(以實際環境為準)如圖 3.2 所示。
圖 3.2 選擇動態庫頭文件路徑
接著封裝動態庫,主要分為4步:
a、包含Python頭文件;
添加頭文件:#include <Python.h>
b、利用樣板來包裝函數;
將lib_demo中的fact()函數封裝如下(并非修改原函數,而是添加封裝函數)
static PyObject *lib_demo_fact(PyObject *self,PyObject *args) {
int num;
if(!(PyArg_ParseTuple(args,"i",&num))) { //獲取Python傳遞的參數
return NULL;
}
return (PyObject*)Py_BuildValue("i",fact(num));
//將結果轉換為Python類型并返回
}
c、為每個模塊增加PyMethodDef ModuleMethods[]數組;
static PyMethodDef lib_demoMethods [] = {
{"fact",lib_demo_fact,METH_VARARGS}, //函數名,包裝函數名,解析
{"hello",lib_demo_hello,METH_NOARGS},
{"lib_func",lib_demo_lib_func,METH_NOARGS},
{NULL,NULL}, //作為結束
};
d、編寫初始化函數。
static struct PyModuleDef lib_demoModule = {
PyModuleDef_HEAD_INIT, //默認
"lib_demo", //模塊名
NULL,
-1,
lib_demoMethods //上面的數組
};
PyMODINIT_FUNC
PyInit_lib_demo(void)
{
return PyModule_Create(&lib_demoModule);
}
封裝完成后的lib_demo如程序清單 3.2 所示。
程序清單 3.2 封裝完成的lib_demo
#include <Python.h>
#include <stdio.h>
int lib_func (void)
{
printf("lib_func call!\n");
return 0;
}
int hello (void)
{
printf("Hello SylixOS!\n");
return 0;
}
int fact(int n)
{
if (n <= 1)
return 1;
else
return n * fact(n - 1);
}
static PyObject *lib_demo_fact(PyObject *self,PyObject *args) {
int num;
if(!(PyArg_ParseTuple(args,"i",&num))) { //獲取Python傳遞的參數
return NULL;
}
return (PyObject*)Py_BuildValue("i",fact(num)); //將結果轉換為Python類型并返回
}
static PyObject *lib_demo_hello(PyObject *self,PyObject *args) {
return (PyObject*)Py_BuildValue("i",hello());
}
static PyObject *lib_demo_lib_func(PyObject *self,PyObject *args) {
return (PyObject*)Py_BuildValue("i",lib_func());
}
static PyMethodDef lib_demoMethods[] = {
{"fact",lib_demo_fact,METH_VARARGS},//函數名,包裝函數名,解析
{"hello",lib_demo_hello,METH_NOARGS},
{"lib_func",lib_demo_lib_func,METH_NOARGS},
{NULL,NULL},//作為結束
};
static struct PyModuleDef lib_demoModule = {
PyModuleDef_HEAD_INIT, //默認
"lib_demo", //模塊名
NULL,
-1,
lib_demoMethods //上面的數組
};
PyMODINIT_FUNC
PyInit_lib_demo(void)
{
return PyModule_Create(&lib_demoModule);
}
將編譯完成后的lib_demo.so上傳至目標設備的/lib/python3/lib/python3.6/lib-dynload目錄下。創建并編輯python腳本test2.py,內容如下。
import lib_demo as demo
print("-------------")
demo.lib_func()
print("-------------")
demo.hello()
print("-------------")
print(demo.fact(10))
print("-------------")
保存后執行“python test2.py”,輸出結果如圖 3.3 所示。
圖 3.3 test2腳本執行結果
腳本運行結果顯示,lib_demo模塊能被成功導入。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。