2013-08-26 32 views
5

我想知道是否有任何方法將C++類暴露給Python,但沒有構建中間共享庫。如何在不構建模塊的情況下將C++類暴露給Python

這是我的理想場景。例如,我有下面的C++類:

class toto 
    { 
    public: 
     toto(int iValue1_, int iValue2_): iValue1(iValue1_), iValue2(iValue2_) {} 
     int Addition(void) const {if (!this) return 0; return iValue1 + iValue2;} 

     private: 
     int iValue1; 
     int iValue2; 
    }; 

我想以某種方式轉換這個類(或其intance)到的PyObject *,以將其作爲paremter(參數)到例如PyObject_CallObject:

PyObject* PyObject_CallObject(PyObject* wrapperFunction, PyObject* args) 

在我的Python側另一方面,我將有一個wrapperFunction這令我非常C++類(或其實例)作爲參數的指針,並調用它的方法,或者使用其屬性:

def wrapper_function(cPlusPlusClass): 
    instance = cPlusPlusClass(4, 5) 
    result = instance.Addition() 

正如你所看到的,我並不需要/想要有一個單獨的共享庫或者通過boost python構建模塊。我需要的是找到一種方法將C++代碼轉換爲PyObject並將其發送給python。我無法找到通過C python庫,boost或swig來實現的方法。

你有什麼想法嗎? 感謝您的幫助。

+1

的 情況下,我不知道我知道你想要什麼。 Boost.Python有'boost :: python :: object :: ptr',它返回一個'PyObject *' - 這是你在找什麼? –

+1

我相信可以通過'ctypes'訪問C/C++,但是暴露一個C++類可能是一件困難的事情。 – Bakuriu

+0

@PaulManta:謝謝你的回答。我想要的包括3個步驟:第1步:在PyObject指針中封裝一個C++類。步驟2將此指針發送給一個python函數。第三步。在python中使用這個C++指針(即調用它的方法)。所以,你可以請更實用,並告訴通過一個例子如何封裝C++代碼到object :: ptr? –

回答

1

我找到了我的答案。其實我在尋找是相當類似這樣的回答(爲他的評論感謝moooeeeep):

Exposing a C++ class instance to a python embedded interpreter

下面的C++類(注意!默認構造函數是必需的):

class TwoValues 
{ 
public: 
    TwoValues(void): iValue1(0), iValue2(0) {} 
    TwoValues(int iValue1, int iValue2): iValue1(iValue1_), iValue2(iValue2_) {} 

    int Addition(void) const {if (!this) return 0; return iValue1 + iValue2;} 

public: 
    int iValue1; 
    int iValue2; 
}; 

可能會暴露通過下面的宏升壓:

BOOST_PYTHON_MODULE(ModuleTestBoost) 
{ 
class_<TwoValues>("TwoValues") 
    .def("Addition",    &TWOVALUES::Addition) 
    .add_property("Value1",  &TWOVALUES::iValue1) 
    .add_property("Value2",  &TWOVALUES::iValue2); 
}; 

在另一方面我在python_script.py WHI定義的Python函數ch需要這個類的一個實例並做一些事情。例如:

def wrapper_function(instance): 
    result = instance.Addition() 
    myfile = open(r"C:\...\testboostexample.txt", "w") 
    output = 'First variable is {0}, second variable is {1} and finally the addition is {2}'.format(instance.Value1, instance.Value2, result) 
    myfile .write(output) 
    myfile .close() 
在C++側

然後,我可以在同一時間發送我的類的實例,像這樣調用這個函數:

Py_Initialize(); 

try 
    { 
    TwoValues instance(5, 10); 
    initModuleTestBoost(); 

    object python_script = import("python_script"); 
    object wrapper_function = python_script.attr("wrapper_function"); 
    wrapper_function(&instance); 
    } 
catch (error_already_set) 
    { 
    PyErr_Print(); 
    } 

Py_Finalize(); 

優點:

  • 我不需要建立任何共享庫或二進制文件
  • 由於我使用Boost,我不需要擔心內存管理 &引用計數
  • 我不使用共享升壓指針(升壓:: shared_ptr的)指向我的課
6

據我所知,有沒有簡單的方法來實現這一點。要使用C++擴展Python既不需要模塊,也不需要中間庫,它需要動態加載庫,然後導入函數。 ctypes模塊使用此方法。爲了實現與C++相同的功能,需要編寫一個類似於的庫來理解目標編譯器的C++ ABI。

要在不引入模塊的情況下擴展Python,可以創建一個提供包裝C++庫的C API的中間庫。這個中間庫然後可以通過​​在Python中使用。儘管它沒有提供確切的調用語法,並且引入了一箇中間庫,但它可能比構建一個類似於的庫更省力,它可以直接與C++接口。

但是,如果要引入中間庫,則可能需要使用Boost.Python,SWIG或其他一些C++/Python語言綁定工具。雖然這些工具中的很多都會通過模塊引入擴展,但它們通常會提供更清晰的調用約定,在綁定過程中更好地進行錯誤檢查,並且可能更易於維護。

+0

非常好的答案。涵蓋了我想說的一切和更多(所以我甚至不會回答;) – nneonneo

相關問題