SylixOS Python擴展庫開發

1 適用範圍

本文檔適用於希望使用基於SylixOS進行Python擴展庫開發的用戶。

2 SylixOS Python簡介

Python是一門面向對象的解釋型的腳本語言,Python具有豐富和強大的庫。它常被暱稱爲膠水語言,能夠把用其他語言製作的各種模塊(尤其是C/C++)很輕鬆地聯結在一起。常見的一種應用情形是,使用Python快速生成程序的原型(有時甚至是程序的最終界面),然後對其中有特別要求的部分,用更合適的語言改寫,比如3D遊戲中的圖形渲染模塊,性能要求特別高,就可以用C/C++重寫,而後封裝爲Python可以調用的擴展類庫。

目前SylixOS支持的Python3.6.4版本,支持絕大多數內建庫,但並未移植擴展庫。

3 SylixOS Python擴展庫開發

可擴展性是Python的一大特色,Python的擴展庫可以基於Python語言開發,也可通過CJAVA等語言進行開發。

本文將介紹如何使用RealEvo-IDE開發C語言版本的SylixOS Python擴展庫。C語言版本Python擴展庫開發有以下兩種方式。

3.1 基於python ctypes模塊開發

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 所示。

image.png

 3.1 python腳本執行結果

腳本執行結果顯示,動態庫內的函數被成功調用。

 

3.2 基於Python擴展庫模板開發

除了使用ctypes直接導入SylixOS動態庫外,python本身也提供自定義擴展庫的模板。通過模板封裝的C/C++動態庫,可以直接使用python的“import”方法導入模塊。

依然以lib_demo爲例,首先需要添加所需頭文件的路徑。頭文件在SylixOS/lib/python3/include目錄下提供,可自行拷貝至開發的動態庫目錄下。環境配置(以實際環境爲準)如 3.2 所示。image.png

 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 所示。

image.png

 3.3 test2腳本執行結果

腳本運行結果顯示,lib_demo模塊能被成功導入。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章