2013-08-26 17 views
5

Tôi muốn biết nếu có cách nào để trưng ra một lớp C++ cho Python nhưng không xây dựng một thư viện chia sẻ trung gian.Làm thế nào để trưng ra một lớp C++ cho Python mà không xây dựng một mô-đun

Đây là kịch bản mong muốn của tôi. Ví dụ tôi đã sau lớp 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; 
    }; 

Tôi muốn chuyển đổi bằng cách nào đó lớp này (hoặc intance của nó) vào một PyObject * để gửi nó như paremter (args) để ví dụ PyObject_CallObject:

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

Mặt khác ở bên python của tôi, tôi sẽ có một wrapperFunction mà được con trỏ trên C của tôi ++ lớp (hoặc cá thể của nó) như tham số và nó gọi phương thức của nó hoặc sử dụng tính chất của nó:

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

Như bạn thấy, tôi không thực sự cần/muốn có một thư viện chia sẻ riêng biệt hoặc xây dựng một mô-đun bằng cách tăng python. Tất cả những gì tôi cần là tìm cách chuyển đổi mã C++ thành PyObject và gửi nó sang python. Tôi không thể tìm thấy một cách để làm điều đó bằng thư viện python C, tăng hoặc SWIG.

Bạn có ý tưởng gì không? Cảm ơn sự giúp đỡ của bạn.

+1

Tôi không chắc là tôi hiểu chính xác những gì bạn muốn. Boost.Python có 'boost :: python :: object :: ptr', trả về' PyObject * '- đây có phải là thứ bạn đang tìm không? –

+1

Tôi tin rằng có thể truy cập C/C++ qua 'ctypes', nhưng nó có thể là một nhiệm vụ khó khăn khi trưng ra một lớp C++. – Bakuriu

+0

@PaulManta: Cảm ơn câu trả lời. Những gì tôi muốn bao gồm trong 3 bước: Bước 1: đóng gói một lớp C++ trong PyObject pointer.Step2 gửi con trỏ này đến một hàm python. Bước 3. sử dụng con trỏ C++ này trong python (tức là gọi các phương thức của nó). Vì vậy, bạn có thể xin được thực tế hơn và nói được bằng một ví dụ làm thế nào tôi có thể đóng gói mã C + + để đối tượng :: ptr? –

Trả lời

1

Tôi đã tìm thấy câu trả lời của mình. Trên thực tế những gì tôi đang tìm kiếm là khá giống với câu trả lời này (nhờ moooeeeep cho bình luận của ông):

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

Sau lớp C++ (! Attention constructor mặc định là bắt buộ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; 
}; 

thể bị ảnh hưởng bằng cách tăng theo macro sau:

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

Mặt khác, tôi có hàm python được xác định trong python_script.py whi ch lấy một thể hiện của lớp này và làm một cái gì đó.Ví dụ:

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() 

Sau đó ở bên C++, tôi có thể gọi chức năng này bằng cách gửi cùng một lúc các thể hiện của lớp học của tôi, như thế này:

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(); 

Ưu điểm:

  • Tôi không cần xây dựng bất kỳ thư viện được chia sẻ nào hoặc số nhị phân
  • Vì tôi đang sử dụng Boost, tôi không cần phải lo lắng về việc quản lý bộ nhớ & tham khảo đếm
  • tôi không sử dụng chia sẻ con trỏ tăng (tăng :: shared_ptr) để trỏ đến thể hiện của lớp học của tôi
6

Theo như tôi biết, không có cách nào dễ dàng để thực hiện việc này.

Để mở rộng Python bằng C++ không có mô-đun hoặc thư viện trung gian, nó sẽ yêu cầu tải động thư viện, sau đó nhập các hàm. Cách tiếp cận này được sử dụng bởi mô-đun ctypes. Để thực hiện tương tự với C++, người ta cần phải viết một thư viện ctypes giống như đã hiểu C++ ABI cho (các) trình biên dịch đích.

Để mở rộng Python mà không giới thiệu một mô-đun, một thư viện trung gian có thể được tạo ra cung cấp một API C kết thúc tốt đẹp thư viện C++. Thư viện trung gian này sau đó có thể được sử dụng trong Python thông qua ctypes. Mặc dù nó không cung cấp cú pháp gọi chính xác và giới thiệu một thư viện trung gian, nó có thể sẽ ít nỗ lực hơn việc xây dựng một thư viện ctypes giống như có thể giao tiếp trực tiếp với C++.

Tuy nhiên, nếu một thư viện trung gian sẽ được giới thiệu, bạn có thể sử dụng Boost.Python, SWIG hoặc một số công cụ ràng buộc ngôn ngữ C++/Python khác. Mặc dù nhiều công cụ trong số này sẽ giới thiệu phần mở rộng thông qua một mô-đun, chúng thường cung cấp các quy ước gọi điện rõ ràng hơn, kiểm tra lỗi tốt hơn trong quá trình ràng buộc và có thể dễ bảo trì hơn.

+0

Câu trả lời rất hay. Bao gồm tất cả mọi thứ tôi muốn nói và nhiều hơn nữa (vì vậy tôi thậm chí sẽ không trả lời;) – nneonneo

Các vấn đề liên quan