多多色-多人伦交性欧美在线观看-多人伦精品一区二区三区视频-多色视频-免费黄色视屏网站-免费黄色在线

國內最全IT社區平臺 聯系我們 | 收藏本站
阿里云優惠2
您當前位置:首頁 > php開源 > php教程 > 工程腳本插件方案 - c集成Python基礎篇

工程腳本插件方案 - c集成Python基礎篇

來源:程序員人生   發布時間:2016-06-04 09:01:55 閱讀次數:3237次

工程腳本插件方案 - c集成Python基礎篇

序: 為何要集成腳本,怎樣在工程中集成Python腳本。

在做比較大型的工程時,1般都會分核心層和業務層。核心層要求實現高效和穩定的基礎功能,并提供調用接口供業務層調用的1種標準的框架劃分。在實際中根據需求會拆分的更細。

外部的表現情勢就是1個核心動態庫,帶著1堆業務業務動態庫。通過1個調度程序把這些鏈接起來,外加1堆配置文件,就構成1個完成的項目。

這類模式在1個團隊開發中,工作職責比較容易劃分。制定API接口后,開發工作基本可以并行實現,包括后期的功能測試(白盒、黑盒)。不管工程使用甚么語言,基本都是如此。

c語言無疑是很強大而又靈活的,但是開發比較復雜,開發工期比較長。全部使用c/c++ 進行開發的話,編譯調試整合發布,就需要大量時間,包括運營保護的話,呵呵~ 。全部產品的生命周期需要投入大量的人力來保持這個產品。特別是對做定制的終究用戶的話,那便可能就是1場曠日持久戰。

剛才說的1般工程都會包括2方面,核心和擴大。是公司級產品的話,1定會出于盈利問題,會對核心做保密(商業機密)。擴大是在核心基礎上實現的,很大程度上保密等級就沒那末高,乃至可以是開放式的。方便有1定能力的用戶直接擴大。這是最理想的1種情況。

如果業務層還是使用c/c++的話,估計用戶沒有幾個有能力或說不太愿意去做擴大。只能公司團隊進行保護和擴大。固然開源項目除外,活躍的開源項目還是有很多大俠們愿意去擴大的。當下降擴大的難度,不但可以縮短開發周期下降本錢,下降運營保護本錢。如果產品夠優秀,還能吸引有1定能力的客戶來幫忙做擴大。擴大簡單方便,用戶自己都能擴大,項目運營本錢一定下降。這就皆大歡樂。

腳本是1個非常方便的東西,不需要編譯直接運行就可以看到結果。不用斟酌大量系統相干的開發技能,更貼近實際業務的描寫,修正問題不需要重新編譯發布,保護非常方便。能大大提供生產效力,這就是我們所須要的。現在流行的腳本語言有很多Ruby、Perl、Python、Lua、Javascript等等。。。,反正很多。

腳本語言比較:

1、python: 簡單易學,有大量擴大可使用。
2、Ruby: 魔幻型純面向對象語言,非常靈活,學習相對其他語言有1定難度。
3、Lua: 超輕量級,性能高效。很多游戲使用Lua提供擴大。

使用那種腳本作為擴大,要看實際項目和現有資源的情況而定。本文只介紹python的集成。

空話這么多,主要的目的就下面幾個。

擴大目的:

1、高可配性。 解決1些簡單配置不能實現的組織、回調功能,避免改動重編重發布。
2、為了使用已有的庫。 如原來你有很多積累,寫了1些合適工程開發的庫。
3、優化程序提升性能。 對腳本程序使用庫的1種情況。

集成: 就是通過簡單、直接和快速的在不同語言直接調度切換控制,屬于無縫連接。就像使用同1種語言在不同的動態庫之間調度。而不是那種使用套接字和管道等的間接調度。

混合開發中,不管python或C都可以作為“上層”。因此兩方面都要提供入口提供對方調度。這個其實和正常的同1語言編寫的插件模式是1致的。核心提供接口和注冊入口,擴大注冊入口并調用接口。

嵌入接口: C程序中運行Python的代碼
擴大接口: Python程序中運行C的代碼庫

測試環境:
window 7
vs2015
python 3.5

1、準備環境

使用的Python是3.5版本的。

首先肯定是須要個python的運行環境,可以直接從官網python.org下載Python3.x 進行安裝。建議直接下源代碼編譯,由于里面有很多代碼可以參考。

windows配置

python安裝路徑以下為例d:\python,在系統的用戶環境變量中添加。

1、 增加python搜索路徑,方便代碼運行調試

path=d:\python;d:\python\pcbuild\win32

2、 增加python環境路徑。加載模塊時默許會從配置路徑中搜索。

PYTHONPATH=.;d:\python\lib;d:\python\pcbuild\win32;D:\Python\Lib\site-packages;d:\python

3、 增加編譯路徑。

PyInc=d:\python\include;d:\python\pc PyLib=d:\python\pcbuild\win32

方便VS搜索路徑配置。在工程中,只需援用配置變量路徑,可以直接使用(PyInc)(PyLib)。

提示: 由因而自己編譯的,1些環境參數沒有須要自己加。注意大小寫

2.1、嵌入Python第1個簡單工程

創建測試工程

在VS中創建1個空的VC++控制臺程序。在工程選擇的搜索目錄中加入$(PyInc)

選擇菜單:Project->Properties...

VC++ Directories分類的Include Directories中加入先前定義的環境變量$(PyInc)。確保Python的頭文件能搜索到。

使用環境變量的1個好處是,方便不同機器不同環境的切換,不需要修改工程配置。

提示: 可以不建工程,直接使用makefile方式進行編譯。

創建script.py腳本

在工程中創建1個新文件,直接改名為script.py,復制下面內容。

注意: 編碼設置為UTF⑻

""" 在C中調用Python模塊運行。 調用時須要把文件放在程序當前運行目錄(保證在搜索目錄中)。 www.moguf.com 2016-05⑵8 """ message = 'hello life...' def transform(input): input = input.replace('life', 'Python') return input.upper()

在Python環境中運行這個腳本,可以得到下面結果。可以看到打印出 hello life... 和轉換后的字符串 HELLO PYTHON...

Microsoft Windows [版本 6.1.7601] 版權所有 (c) 2009 Microsoft Corporation。保存所有權利。 C:\Users\CrystalIce>cd /d D:\Dev\MySimple\pythoninc\embedsimple D:\Dev\MySimple\pythoninc\embedsimple>python Running Release|Win32 interpreter... Python 3.5.0 (default, Nov 4 2015, 21:58:28) [MSC v.1900 32 bit (Intel)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> import script >>> print(script.message) hello life... >>> x = script.message >>> print(script.transform(x)) HELLO PYTHON... >>>

創建hello.c

在工程中添加1個新文件,命名為hello.c。復制下面內容。

// // C code runs Python code in this module in embedded mode. // print hello string // // www.moguf.com 2016-05⑵8 // #include <python.h> int main() { Py_Initialize(); PyRun_SimpleString("print('run python ...')"); PyRun_SimpleString("import script"); PyRun_SimpleString("print(script.message)"); PyRun_SimpleString("x = script.message"); PyRun_SimpleString("print(script.transform(x))"); Py_Finalize(); }

運行程序

在程序最后下個斷點,方便查看運行結果。直接運行程序可以看到下面結果。

run python ... hello life... HELLO PYTHON...

基本調用流程解析

使用C程序運行Python腳本代碼,可以通過使用Python字符串,調用Python對象或模板之類的所有操作。

流程:
1、初始化Python解析器
2、履行Python代碼,字符串,對象或模塊。
3、關閉Python解析器。

上面代碼嵌入進程很容易。但在實際使用中想要更好的整合,須要了解提供的API和不同語言之間的轉換。

Python嵌入C的基礎API

下面幾個基礎API,在C中能很容易的履行Python腳本中的代碼。包括字典、數組和對象。固然想要更好的混合交互須要熟習所有的API。

C API 調用 Python 對應
PyImport_ImportModel import module
PyImport_ReloadModule reload(module)
PyImport_GetModuleDict module.__dict__
PyDict_GetItemString dict[key]
PyDict_SetItemString dict[key] = value
PyDict_New dict = {}
PyObject_GetAttrString getattr(obj, attr)
PyObject_SetAttrString setattr(obj, attr, val)
PyObject_CallObject funcobj(*argstuple)
PyEval_CallObject funcobj(*argstuple)
PyRun_String eval(exprstr) , exec(stmtstr)
PyRun_File exec(open(filename().read())

建議: 去官網下載1個手冊,方便查看API。https://docs.python.org/3/download.html

2.2、使用C擴大Python

2.1的內容只是通過C程序調用Python腳本,要讓Python腳本能調用C代碼,就須要擴大。用C擴大Python功能那就簡單很多。有很多實例可以參考。Python源代碼就是寶庫。

創建擴大工程 hello

在VS中創建1個空的動態庫hello工程(先不要改名)。在工程配置中增加搜索路徑。

在VS生成時有些特殊。生成的后綴選擇.pyd主要是為避免和系統.dll產生沖突。

在工程選項界面中設置工程輸出名稱為$(ProjectName)_d,輸出擴大名稱為.pyd

并在Linker頁面Input組中設置庫依賴為python35_d.lib

不同的編譯模式的設置:
Release 下使用的依賴庫為pythonXY.lib
Debug 下使用依賴庫為 pythonXY_d.lib

注意:
debug 模式生成應為 hello_d.pyd
release 模式生成應為 hello.pyd

創建hello.c擴大代碼

在工程中新建hello.c文件,復制下面內容。

// // A simple C extension module for python, called "hello" // // www.moguf.com 2016-05⑵8 // #include <python.h> #include <string.h> // // module functions // static PyObject * // returns object message(PyObject *self, PyObject *args) { char *fromPython, result[1024]; if (!PyArg_Parse(args, "(s)", &fromPython)) // convert Python -> C return NULL; // exception null = raise else { strcpy(result, "Hello , "); // build up C string strcat(result, fromPython); // add passed Python string return Py_BuildValue("s", result); // convert C -> Python } } // // registration methods table static PyMethodDef hello_methods[] = { { "message", message, METH_VARARGS, "func doc" }, // format: name, &func, fmt, doc { NULL, NULL, 0, NULL } // end }; // module definition structure static struct PyModuleDef hellomodule = { PyModuleDef_HEAD_INIT, "hello", // module name "mod doc", // module documentation, -1, hello_methods // methods table }; // // module initializer PyMODINIT_FUNC PyInit_hello() { return PyModule_Create(&hellomodule); }

上面的代碼主要分為4塊。

第1塊: 模塊功能實現函數
第2塊: 注冊功能函數
第3塊: 定義模塊申明
第4塊: 初始化模塊。動態加載就不需要這塊內容,集成時會使用動態加載。

通過上述定義為Python腳本調用提供訪問入口,這就是通常所說的膠水代碼。具體定義直接看代碼注釋,就不啰嗦了。

這里須要注意的是定義中的名稱hello。在第3塊模型注冊的時候是名稱為hello、第4塊中函數的初始化名稱PyInit_hello()。在python3中的名稱規定比較嚴格,初始化函數名稱格式為PyInit_xxx, xxx為注冊的模塊名稱。

即對Python擴大工程中的工程名稱注冊名稱初始化名稱須要保持1致。

編譯測試運行

編譯hello工程(debug版本),在Python調試版本下運行。python調試環境使用python_d命令進入。

可以看到下面結果,就說明OK了

Microsoft Windows [版本 6.1.7601] 版權所有 (c) 2009 Microsoft Corporation。保存所有權利。 C:\Users\CrystalIce>cd /d D:\Dev\MySimple\pythoninc\Debug D:\Dev\MySimple\pythoninc\Debug>dir 驅動器 D 中的卷是 Docs 卷的序列號是 0002⑵203 D:\Dev\MySimple\pythoninc\Debug 的目錄 2016-05⑵8 23:10 <dir> . 2016-05⑵8 23:10 <dir> .. 2016-05⑵8 23:10 639 hello_d.exp 2016-05⑵8 23:10 247,520 hello_d.ilk 2016-05⑵8 23:10 1,718 hello_d.lib 2016-05⑵8 23:10 503,808 hello_d.pdb 2016-05⑵8 23:10 35,840 hello_d.pyd 5 個文件 789,525 字節 2 個目錄 27,394,551,808 可用字節 D:\Dev\MySimple\pythoninc\Debug>python_d Python 3.5.0 (default, Nov 4 2015, 21:57:44) [MSC v.1900 32 bit (Intel)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> import hello >>> print(hello.message('C')) Hello , C >>> print(hello.message('module ' + hello.__file__)) Hello , module D:\Dev\MySimple\pythoninc\Debug\hello_d.pyd >>>

如果在運行調試中出現下面情況,是Python找不到hello模塊致使的。

>>> import hello Traceback (most recent call last): File "<stdin>", line 1, in <module> ImportError: No module named 'hello'

大致緣由:

編譯的模塊名稱有問題,加載不到模塊。Python在debug環境下會調用 xxx_d.pyd,release下會調用 xxx.pyd。

創建hellouse.py 調用hello擴大模塊

在工程中新建1個hellouse.py,用于調度hello擴大模塊。

注意: 編碼設置為UTF⑻

內容以下:

""" import and use a C extension library module www.moguf.com 2016-05⑵8 """ import hello print(hello.message('C')) print(hello.message('module ' + hello.__file__))

把這個腳本復制到hello_d.pyd擴大庫所在目錄,并履行 。可以看到和剛才測試輸出的結果是1致的。

D:\Dev\MySimple\pythoninc\Debug>python_d hellouse.py Hello , C Hello , module D:\Dev\MySimple\pythoninc\Debug\hello_d.pyd

相干編譯問題:
如果自己建的工程編譯或調試,老出現狀態。可以直接使用Python提供的PC\example_ntVS示例工程作為參考。

2.3、集成Python,實現雙工

先前的的兩個示例都是單方面調用,c調用Python 和 Python調用c的擴大模型。并沒有交互。在實際工程中不太可能有這類情況,1定是相互交叉調用。

創建duplex工程

在VS中創建1個空的控制臺程序,并設置Python代碼搜索路徑,參照2.1。

創建duplex.c 文件

這個原文件包括了腳本調用和膠水代碼的實現。和2.1、2.2的內容基本1致。其中主要的差異在Python模塊的注冊上

PyImport_AppendInittab("hello_api", &PyInit_hello_api);

實際對外注冊的模塊在程序啟動時履行,并沒有作導出。

文件內容以下。

// // c API module, test c embedding and extending // // www.moguf.com 2016-05⑵9 // #include <python.h> #include <string.h> void helloWorld(char *param) { if (param) printf("It's c, hello %s", param); else printf("It's c, hello "); } static PyObject * message(PyObject *self, PyObject *args) { char *fromPython; if (!PyArg_Parse(args, "(s)", &fromPython)) helloWorld(NULL); else helloWorld(fromPython); return Py_BuildValue(""); } static PyMethodDef hello_methods[] = { { "message", message, METH_VARARGS, "func doc" }, { NULL, NULL, 0, NULL } // end }; static struct PyModuleDef hello_api = { PyModuleDef_HEAD_INIT, "hello_api", "mod doc", -1, hello_methods }; static PyObject* PyInit_hello_api(void) { return PyModule_Create(&hello_api); } int main(int argc, char** argv) { PyObject* module; PyObject* func; // add c api to modules PyImport_AppendInittab("hello_api", &PyInit_hello_api); Py_Initialize(); if (!Py_IsInitialized()) { PyErr_Print(); printf("Couldn't init python"); return -1; } module = PyImport_ImportModule("plugins"); if (module) { func = PyObject_GetAttrString(module, "helloWorld"); if (func && PyCallable_Check(func)) { PyObject* pArgs = NULL; PyObject* pReturnVal = PyObject_CallObject(func, pArgs); } else { PyErr_Print(); printf("error: no func\n"); } Py_XDECREF(func); Py_DECREF(module); } else { PyErr_Print(); printf("err: no module"); } Py_Finalize(); return 0; }

創建腳本plugins.py

內容以下

""" Module to test c embedding and extending www.moguf.com 2016-05⑵9 """ import hello_api def helloWorld(): print("it's Python, Hello C") hello_api.message('python') return

運行測試

在 main函數結束的位置設置斷點,這用方便查看結果。運行程序。

it's Python, Hello C It's c, hello python

可以看到,第1行打印是由Python腳本實現輸出,第2行是由python調用程序的API實現打印輸出。

3、后續

通過上述簡單的3個實例實現了c語言和Python腳本的集成。簡單、直接和快速的在不同語言直接調度切換控制。

由于Python開始時本身就是基于C寫的,所有對c的支持是非常好的。能在c/c++中很方便的進行集成。不過要想更好的實現腳本和C進行交互,那就須要熟習并使用提供的API。

后續將會使用Python腳本作為插件擴大1種模式,在實際工程中實現業務的1些方案。

相干參考:
1、官方幫助 https://docs.python.org/3/
2、源代碼:https://github.com/cmacro/simple/tree/master/pythoninc

生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關閉
程序員人生
主站蜘蛛池模板: 爽好舒服快奶水视频 | 国产在线乱子伦一区二区 | 国产一区二区福利 | 欧美一级毛片欧美一级 | 欧美一区二区三区四区在线观看 | 久久99久久99精品免观看麻豆 | 久久久久久午夜精品 | 午夜欧美福利 | 伊人影院视频 | 狂野黑人性猛交xxxxxx | 国产chinesehdxxxxtube | 另类 校园 春色 都市 亚洲 | 欧美性受xxxx喷水大胸 | 能看毛片的网址 | 五月天基地 | 亚洲欧美综合乱码精品成人网 | 国产精品免费久久久久影院 | 亚洲成aⅴ人片在线影院八 亚洲成aⅴ人在线观看 | 在线观看三级视频 | 欧美日韩在线一区二区三区 | 日本韩国欧美三级 | 亚洲人成网站在线观看播放青青 | 国产视频自拍一区 | 一区二区三区在线观看视频 | 欧美日韩一区二区三区麻豆 | 午夜视频免费看 | 欧美在线天堂 | 日本a∨在线播放高清 | 国产欧美一区二区精品性色 | 波多野结衣手机在线视频 | 欧美白人和黑人xxxx猛交视频 | 亚洲国产一级毛片 | 毛片网此 | 国产一区亚洲二区三区毛片 | 亚洲韩精品欧美一区二区三区 | 免费澳门一级毛片 | 欧美第一页 | 国产精品久久久免费视频 | 午夜影院在线看 | 综合久久精品 | 国产精品videossex激情 |