I'm try to binding a C++ library with pybind11. I have a class that generates the instance with which to call the main functions that I don't know how to bind.
/*!
* @/class FOO_API
* @/brief Structure for API support
*/
class FOO_API {
public:
/*!
* @fn Instance
* @brief Class instance constructor FOO_API
* @return FOO_API* Return an initialized FOO_API object
*/
static FOO_API* instance(struct config1 conf1, struct config2 conf2);
/*!
* @fn Liberate
* @brief Free memory
*/
static void liberate();
private:
/*!
* @fn FOO_API()
* @brief Create an empty object FOO_API
*/
FOO_API();
/*!
* @fn FOO_API(const FOO_API& orig)
* @brief Create object from another
* @param orig { Param FOO_API }
*/
FOO_API(const FOO_API& orig);
/*!
* @fn virtual ~FOO_API()
* @brief Free memory
*/
virtual ~FOO_API();
static FOO_API* m_pInstance;
static class FOO_API_Impl* m_pInstanceImpl;
};
In the wrapper file I put something like that:
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include "FOO_API.h"
namespace py = pybind11;
PYBIND11_MODULE(example, m) {
m.doc() = "pybind11 example plugin";
py::class_<config1>(m, "config1")
.def(py::init<>())
.def_readwrite("foo", &config1::foo)
py::class_<config2>(m, "config2")
.def(py::init<>())
.def_readwrite("bar", &config2::bar)
py::class_<FOO_API>(m, "FOO_API")
.def(py::init<>())
m.def("instance", &instance);
When I'm trying compile the wrapper I get this error:
error: ‘instance’ was not declared in this scope
m.def("instance", &instance);
How should I create the FOO_API class and how should I call the instance() function from wrapper c++ code? Thanks for your comments
UPDATE 1:
Changing the FOO_API class following Rahut's recommendation
// Exposing FOO_API class and its static methods
py::class_<FOO_API, std::unique_ptr<FOO_API, py::nodelete>>(m, "FOO_API")
// Use py::init to expose the constructor, but the constructor is private
// so we are not exposing it directly.
.def_static("instance",
static_cast<FOO_API* (*)(config1, config2)>(&FOO_API::instance),
py::return_value_policy::reference)
.def_static("liberate", &FOO_API::liberate);
And calling the bind function from python code like this
import example as wrapper
conf1 = wrapper.config1
conf2 = wrapper.config2
pointerFOO_API = wrapper.FOO_API.instance(conf1, conf2)
returned this error
Traceback (most recent call last):
File "main.py", line 160, in <module>
pointerFOO_API = wrapper.FOO_API.instance(conf1, conf2)
TypeError: instance(): incompatible function arguments. The following argument types are supported:
1. (arg0: example.config1, arg1: example.config2) -> example.FOO_API
Invoked with: <class 'example.config1'>, <class 'example.config2'>
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include "FOO_API.h"
namespace py = pybind11;
PYBIND11_MODULE(example, m) {
m.doc() = "pybind11 example plugin";
py::class_<config1>(m, "config1")
.def(py::init<>())
.def_readwrite("foo", &config1::foo);
py::class_<config2>(m, "config2")
.def(py::init<>())
.def_readwrite("bar", &config2::bar);
// Exposing FOO_API class and its static methods
py::class_<FOO_API>(m, "FOO_API")
// Use py::init to expose the constructor, but the constructor is private
// so we are not exposing it directly.
.def_static("instance",
static_cast<FOO_API* (*)(config1, config2)>(&FOO_API::instance),
py::arg("conf1"), py::arg("conf2"),
py::return_value_policy::reference)
.def_static("liberate", &FOO_API::liberate);
}
main.py
to test it:
import example as wrapper
# Create instances of config1 and config2
conf1 = wrapper.config1() # Instantiate config1
conf2 = wrapper.config2() # Instantiate config2
# Pass the instances to the FOO_API.instance() method
pointerFOO_API = wrapper.FOO_API.instance(conf1, conf2)
# Now you can use pointerFOO_API