[C++/Python] 如何在C++中使用一個Python類? (Use Python-defined class in C++)


最近在做基於OpenCV的車牌識別, 其中需要用到深度學習的一些代碼(Python), 所以一開始的時候開發語言選擇了Python(禍患之源).

固然現在Python的速度不算太慢, 但你一定要用Python來操作圖像, 實現某些算法的時候, 效率就變得非常重要. 可惜的是, Python在大多數算法實現中, 由於其循環操作實在是太慢, 導致實現的算法效率非常之低.

所以現在我要把深度學習中的一個類(分類器)轉換到C++中, 在這個過程之前, 需要做一些test projects, 我主要參照的文章是: C++調用Python(3).

開發環境為 VS2012, WIN7 64.

所有代碼都在最后放出, 這里先逐步講解.

首先我們需要導入合適的頭文件: Python.h, 它位於你的Python安裝目錄的include目錄下. (2.6, 2.7版本實測通過)

使用VS的話, 可以按如下方法設置一下項目屬性:

  1. 調試 -> xxx屬性(最后一欄) -> VC++目錄 -> 右側庫目錄
  2. 增加C:\Python27\libs, 具體路徑個人可能不同.

這樣就完成了最基本的配置, 下面我們開始導入.py文件並使用它.

我們使用的.py文件非常簡單, 代碼如下:

 1 #!/usr/bin/python
 2 # Filename: testpy.py
 3 class Person:  4     def sayHi(self):  5         print 'hi'
 6 class Second:  7     def invoke(self,obj):  8  obj.sayHi()  9 def sayhi(name): 10     print 'hi',name;

注: 下述所有導入方法在導入失敗時不會報錯, 只會返回空指針.

第一步是導入.py文件:

  1. 使用PyObject* pModule來存儲導入的.py文件模塊, 調用的方法是PyImport_ImportModule(path):  PyObject* pModule = PyImport_ImportModule("testpy"); 
  2. 使用PyObject* pDict來存儲導入模塊中的方法字典, 調用的方法是PyModule_GetDict(module):  PyObject* pDict = PyModule_GetDict(pModule); 

這樣就完成了.py文件的導入.

第二步是導入已導入模塊中的方法或類:

  1. 獲取方法, 調用的方法是PyDict_GetItemString(dict, methodName): PyObject* pFunHi = PyDict_GetItemString(pDict, "sayhi"); 
  2. 獲取類, 調用的方法同上, 注意紅體部分的字符串對應於.py文件中的類/方法名:  PyObject* pClassSecond = PyDict_GetItemString(pDict, "Second"); 

第三步是使用導入的方法或類:

  1. 使用方法, 調用PyObject_CallFunction(pFunc, "s", args)即可:  PyObject_CallFunction(pFunHi, "s", "lhb"); 
  2. 使用類構造對象, 調用PyInstance_New(pClass, NULL, NULL)即可:  PyObject* pInstanceSecond = PyInstance_New(pClassSecond, NULL, NULL); , 注意其中的pClassSecond為第二步.2中獲取的類指針
  3. 使用類對象的方法, 調用PyObject_CallMethod(pInstance, methodname, "O", args)即可:  PyObject_CallMethod(pInstanceSecond, "invoke", "O", pInstancePerson); 
  4. 上述調用中的"s"和"O"代表的是參數列表的類型, 我們可以在 Py_BuildValue 找到所有的類型, 本文最后也附了此表.

最后不要忘記銷毀這些對象:  Py_DECREF(pointer); 

下面是C++的實現代碼, 代碼來自於我參考的博客, 略有修改.

 

 1 /*
 2  * test.cpp  3  * Created on: 2010-8-12  4  * Author: lihaibo  5  */
 6 #include <C:/Python27/include/Python.h>
 7 #include <iostream>
 8 #include <string>
 9 
10 int main(void) { 11     Py_Initialize(); // 啟動虛擬機
12     if (!Py_IsInitialized()) 13         return -1; 14     // 導入模塊
15     PyObject* pModule = PyImport_ImportModule("testpy"); 16     if (!pModule) { 17         printf("Cant open python file!/n"); 18         return -1; 19  } 20     // 模塊的字典列表
21     PyObject* pDict = PyModule_GetDict(pModule); 22     if (!pDict) { 23         printf("Cant find dictionary./n"); 24         return -1; 25  } 26     // 演示函數調用
27     PyObject* pFunHi = PyDict_GetItemString(pDict, "sayhi"); 28     PyObject_CallFunction(pFunHi, "s", "lhb"); 29  Py_DECREF(pFunHi); 30     // 演示構造一個Python對象,並調用Class的方法 31     // 獲取Second類
32     PyObject* pClassSecond = PyDict_GetItemString(pDict, "Second"); 33     if (!pClassSecond) { 34         printf("Cant find second class./n"); 35         return -1; 36  } 37     //獲取Person類
38     PyObject* pClassPerson = PyDict_GetItemString(pDict, "Person"); 39     if (!pClassPerson) { 40         printf("Cant find person class./n"); 41         return -1; 42  } 43     //構造Second的實例
44     PyObject* pInstanceSecond = PyInstance_New(pClassSecond, NULL, NULL); 45     if (!pInstanceSecond) { 46         printf("Cant create second instance./n"); 47         return -1; 48  } 49     //構造Person的實例
50     PyObject* pInstancePerson = PyInstance_New(pClassPerson, NULL, NULL); 51     if (!pInstancePerson) { 52         printf("Cant find person instance./n"); 53         return -1; 54  } 55     //把person實例傳入second的invoke方法
56     PyObject_CallMethod(pInstanceSecond, "invoke", "O", pInstancePerson); 57     //釋放
58  Py_DECREF(pInstanceSecond); 59  Py_DECREF(pInstancePerson); 60  Py_DECREF(pClassSecond); 61  Py_DECREF(pClassPerson); 62  Py_DECREF(pModule); 63     Py_Finalize(); // 關閉虛擬機
64     return 0; 65 }

 類型參照:

s (string) [char *]
Convert a null-terminated C string to a Python object. If the C string pointer is NULLNone is used.
s# (string) [char *, int]
Convert a C string and its length to a Python object. If the C string pointer is NULL, the length is ignored and None is returned.
z (string or None) [char *]
Same as s.
z# (string or None) [char *, int]
Same as s#.
u (Unicode string) [Py_UNICODE *]
Convert a null-terminated buffer of Unicode (UCS-2 or UCS-4) data to a Python Unicode object. If the Unicode buffer pointer is NULLNoneis returned.
u# (Unicode string) [Py_UNICODE *, int]
Convert a Unicode (UCS-2 or UCS-4) data buffer and its length to a Python Unicode object. If the Unicode buffer pointer is NULL, the length is ignored and None is returned.
i (integer) [int]
Convert a plain C int to a Python integer object.
b (integer) [char]
Convert a plain C char to a Python integer object.
h (integer) [short int]
Convert a plain C short int to a Python integer object.
l (integer) [long int]
Convert a C long int to a Python integer object.
B (integer) [unsigned char]
Convert a C unsigned char to a Python integer object.
H (integer) [unsigned short int]
Convert a C unsigned short int to a Python integer object.
I (integer/long) [unsigned int]
Convert a C unsigned int to a Python integer object or a Python long integer object, if it is larger than sys.maxint.
k (integer/long) [unsigned long]
Convert a C unsigned long to a Python integer object or a Python long integer object, if it is larger than sys.maxint.
L (long) [PY_LONG_LONG]
Convert a C long long to a Python long integer object. Only available on platforms that support long long.
K (long) [unsigned PY_LONG_LONG]
Convert a C unsigned long long to a Python long integer object. Only available on platforms that support unsigned long long.
n (int) [Py_ssize_t]

Convert a C Py_ssize_t to a Python integer or long integer.

New in version 2.5.

c (string of length 1) [char]
Convert a C int representing a character to a Python string of length 1.
d (float) [double]
Convert a C double to a Python floating point number.
f (float) [float]
Same as d.
D (complex) [Py_complex *]
Convert a C Py_complex structure to a Python complex number.
O (object) [PyObject *]
Pass a Python object untouched (except for its reference count, which is incremented by one). If the object passed in is a NULL pointer, it is assumed that this was caused because the call producing the argument found an error and set an exception. Therefore, Py_BuildValue()will return NULL but won’t raise an exception. If no exception has been raised yet, SystemError is set.
S (object) [PyObject *]
Same as O.
N (object) [PyObject *]
Same as O, except it doesn’t increment the reference count on the object. Useful when the object is created by a call to an object constructor in the argument list.
O& (object) [converteranything]
Convert anything to a Python object through a converter function. The function is called with anything (which should be compatible withvoid *) as its argument and should return a “new” Python object, or NULL if an error occurred.
(items) (tuple) [matching-items]
Convert a sequence of C values to a Python tuple with the same number of items.
[items] (list) [matching-items]
Convert a sequence of C values to a Python list with the same number of items.
{items} (dictionary) [matching-items]
Convert a sequence of C values to a Python dictionary. Each pair of consecutive C values adds one item to the dictionary, serving as key and value, respectively.

If there is an error in the format string, the SystemError exception is set and NULL returned.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM