2016-10-04 3 views
1

Я пытаюсь создать привязку python с pybind11, которая ссылается на экземпляр C++, память которого обрабатывается на стороне C++. Вот несколько примеров коды:Ссылка на выделенный объект C++ в pybind11

import <pybind11/pybind11> 

struct Dog { 
    void bark() { printf("Bark!\n"); } 
}; 

int main() 
{ 
    auto dog = new Dog; 
    Py_Initialize(); 
    initexample(); // Initialize the example python module for import 

    // TBD - Add binding between dog and example.dog . 

    PyRun_StringFlags("import example\n" 
        "\n" 
        "example.dog.bark()\n" // Access the C++ allocated object dog. 
        , Py_file_input, main_dict, main_dict, NULL); 
    Py_Finalize(); 
} 

я застрял на том, как создать связь между питоном example.dog и переменного C++ dog.

Я не могу использовать py:class_<Dog>.def(py::init<>()), так как это выделит новый экземпляр Dog, который не является тем, что я хочу.

ответ

2

Я нашел ответ на свой вопрос. Трюк представлял собой сочетание двух следующих концепций:

  • Создайте независимую функцию, которая возвращает одноэлементный режим.
  • Создать привязку к классу singleton без привязка конструктора.

Следующий пример иллюстрирует метод:

#include <Python.h> 
#include <pybind11/pybind11.h> 

namespace py = pybind11; 
using namespace pybind11::literals; 

// Singleton to wrap 
struct Singleton 
{ 
    Singleton() : x(0) {} 

    int exchange(int n) // set x and return the old value 
    { 
    std::swap(n, x); 
    return n; 
    } 

    // Singleton reference 
    static Singleton& instance() 
    { 
    static Singleton just_one; 
    return just_one; 
    } 

    int x; 
}; 

PYBIND11_PLUGIN(example) { 
    py::module m("example", "pybind11 example plugin"); 

    // Use this function to get access to the singleton 
    m.def("get_instance", 
      &Singleton::instance, 
      py::return_value_policy::reference, 
      "Get reference to the singleton"); 

    // Declare the singleton methods 
    py::class_<Singleton>(m, "Singleton") 
     // No init! 
     .def("exchange", 
      &Singleton::exchange, 
      "n"_a, 
      "Exchange and return the current value" 
      ) 
     ; 

    return m.ptr(); 
} 

int main(int argc, char **argv) 
{ 
    Py_Initialize(); 

    PyObject* main_module = PyImport_AddModule("__main__"); 
    PyObject* main_dict = PyModule_GetDict(main_module); 

    initexample(); 

    // Call singleton from c++ 
    Singleton::instance().exchange(999); 

    // Populate the example class with two static pointers to our instance. 
    if (PyRun_StringFlags("import example\n" 
         "\n" 
         "example.s1 = example.get_instance()\n" 
         "example.s2 = example.get_instance()\n", 
         Py_file_input, main_dict, main_dict, NULL) == nullptr) 
     PyErr_Print(); 

    // Test referencing the singleton references 
    if (PyRun_StringFlags("from example import *\n" 
         "\n" 
         "for i in range(3):\n" 
         " print s1.exchange(i*2+1)\n" 
         " print s2.exchange(i*2+2)\n" 
         "print dir(s1)\n" 
         "print help(s1.exchange)\n" 
         , 
         Py_file_input, main_dict, main_dict, NULL) == nullptr) 
     PyErr_Print(); 

    Py_Finalize(); 

    exit(0); 
} 
Смежные вопросы