簡體   English   中英

如何在不構建模塊的情況下將C ++類公開給Python

[英]How to expose a C++ class to Python without building a module

我想知道是否有任何方法可以將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(args)發送到例如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找到一種方法。

你有什么主意嗎? 謝謝你的幫助。

據我所知,沒有簡單的方法來實現這一目標。

要使用C ++擴展Python既不是模塊也不是中間庫,它需要動態加載庫,然后導入函數。 這種方法由ctypes模塊使用。 library that understood the C++ ABI for the target compiler(s). 要用C ++完成相同的操作,需要編寫一個類似ctypes 庫,它可以理解目標編譯器的C ++ ABI。

為了在不引入模塊的情況下擴展Python,可以創建一個中間庫,它提供了一個包裝C ++庫的C API。 然后可以通過ctypes在Python中使用此中間庫。 library that could interface directly with C++. 雖然它沒有提供確切的調用語法並且確實引入了一個中間庫,但它可能比構建一個可以直接與C ++接口的類似ctypes 庫相比更省力。

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

我找到了答案。 實際上我在搜索的內容與這個答案非常相似(感謝moooeeeep的評論):

將C ++類實例暴露給python嵌入式解釋器

遵循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中定義的python函數,它接受這個類的一個實例並做一些事情。 例如:

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時,我不需要擔心內存管理和引用計數
  • 我不使用共享提升指針(boost :: shared_ptr)指向我的類的實例

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM