2014-01-11 58 views
2

我正在用Python/C API進行一些測試,以瞭解它如何工作以及如何正確使用它。我的目標是創建C++包裝器,它允許我從C++代碼運行Python腳本。 我無法使用外部綁定庫(如Boost.Python或Cython)。一切都很好,除了一兩件事:用PyImport_Import()如何將Python模塊(從PyObject *)轉換並保存爲二進制數據以便稍後使用它?

PyObject* py_module = PyImport_Import(py_module_name); //imports *.py file 
//do something, call functions, save results 
PyDecRef(py_module); 

現在,我加載腳本在發行版本,但是,它們必須分佈在專有的二進制格式,並加載到啓動時的內存。我正在尋找一些提示如何實現這一點 - 沒有結果。基本上,我需要這樣做:

File* file = fopen("scripts.bin", "rb"); 
char* c_buff = malloc(...); 
fread(c_buff, file, ...); 
PyObject* py_module = CreatePyObjectFromBinaryData(c_buff, ...); 

可能smeone提供可能的解決方案嗎?我想過以這種方式使用編組功能:

FILE* file = fopen("scripts.bin", "wb"); 
PyMarshal_WriteObjectToFile(py_module, file, Py_MARSHAL_VERSION); 

但是,這似乎並不奏效。事實上,我不確定哪些對象可以用這種方式進行編組,因爲文檔沒有提到它。

可選問題:我在我的二進制文件夾中有* .py文件。在啓動時,在PyImport_Import()之後,它們被隱式編譯爲/ pycache中的字節碼(.pyc)。我知道字節碼文件( .pyc或* .pyo)可以使用compileall模塊創建。是否可以使用這種文件的內容創建包含模塊數據的PyObject?

+0

你可以只運送Python腳本? – Yakk

+0

這是我被告知的最初要求之一。我負責'偵察' - 可能的解決方案是什麼以及它們有多複雜。如果解決這個問題不容易實現,我們不會強迫它,只是用'原始'腳本來運送應用程序。這很容易 - Py_CompileStringExFlags和PyEval_EvalCodeEx就是這樣。問題是:是否有可能序列化由Py_CompileStringExFlags返回的代碼對象,並使用它的內容而不是原始文件,這是在應用程序啓動時編譯的。 –

+0

@Mateusz> ...每次應用程序啓動時編譯。 < - 這並不完全正確。如果我正確理解你,並且你指的是.pyc python字節碼,它會被生成一次 - 你甚至可以強制從python本身離線生成。鑑於字節碼可以「輕鬆」反編譯,爲什麼不堅持呢?一個簡單的部署腳本可以複製/生成.py文件並強制啓動.pyc生成。 – MariusSiuram

回答

0

發佈.pyc文件可以接受嗎?嘗試是這樣的:

int size; 
unsigned char *python_code; 
PyObject *mainobj; 
size = load_file("multiply.pyc", &python_code);  
Py_Initialize(); 
codeobj = PyMarshal_ReadObjectFromString(python_code+8, size-8); 
mainobj = PyImport_ExecCodeModule("multiply", codeobj); 
Py_Finalize(); 

看到這個討論... https://groups.google.com/forum/#!topic/comp.lang.python/zhIe_Aa2Ih8凡Caersten黑澤說:

一個PYC文件包含以下內容:

1)含有一種神奇的8字節的頭數。 2)代碼對象的「元帥」 序列化。

因此,爲了將這些內容轉換爲代碼對象,您需要 來跳過8字節的標題,其餘部分取消編組。

未能使用包含.pyc文件的加密zip文件? (你需要在你的C++代碼中編碼pwd)。

如果你不信任客戶端,我認爲真正安全的東西真的很難(不可能?)。

相關問題