Consider this little pybind11 wrapper + test:
setup.py
from pybind11.setup_helpers import Pybind11Extension
from pybind11.setup_helpers import build_ext
from setuptools import setup
setup(
name="wrapper",
ext_modules=[Pybind11Extension("wrapper", ["wrapper.cpp"])],
cmdclass={"build_ext": build_ext},
)
wrapper.cpp
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <vector>
namespace py = pybind11;
struct Mesh2d {
public:
Mesh2d(int numVerts, int numTris)
: numVertices(numVerts), numTriangles(numTris) {
vertices = new float[numVerts * 2];
indices = new int[numTris * 3];
}
~Mesh2d() {
delete vertices;
delete indices;
}
void makeVertex(int i, float x, float y) {
vertices[i * 2 + 0] = x;
vertices[i * 2 + 1] = y;
}
void makeTriangle(int i, int a, int b, int c) {
indices[i * 3 + 0] = a;
indices[i * 3 + 1] = b;
indices[i * 3 + 2] = c;
}
float *vertices;
int *indices;
int numVertices;
int numTriangles;
};
PYBIND11_MODULE(wrapper, m) {
m.doc() = "mcve";
py::class_<Mesh2d>(m, "Mesh2d")
.def(py::init<int, int>())
.def("make_vertex", &Mesh2d::makeVertex)
.def("make_triangle", &Mesh2d::makeTriangle)
.def_readonly("vertices", &Mesh2d::vertices)
.def_readonly("indices", &Mesh2d::indices);
}
test.py
from wrapper import Mesh2d
def test():
m = Mesh2d(3, 1)
m.make_vertex(0, -1.0, -1.0)
m.make_vertex(1, 1.0, -1.0)
m.make_vertex(2, 0.0, 1.0)
m.make_triangle(0, 0, 1, 2)
print(m.vertices.__class__)
print(m.indices.__class__)
test()
Question
Right now because I'm not doing anything special to neither vertices nor indices the __class__
I'm getting in python land is <class 'float'>
and <class 'int'>
respectively. What'd be the proper pybind11 way to convert these raw pointers to some suitable object such as:
array.array("f", vertices)
array.array("I", indices)
(ctypes.c_float * 6)(*vertices)
(ctypes.c_uint * 3)(*indices)
memoryview(struct.pack("6f", *vertices))
memoryview(struct.pack("3I", *indices))
struct.pack("6f", *vertices)
struct.pack("3I", *indices)
My end goal here would be being able to generate really complex heavy data on c++ side (heavy data that will be modified in realtime). So having little overhead on the wrapper (ideally without any unnecesary copy to python data structures, just giving the raw pointer).
Reference
https://pybind11.readthedocs.io/en/stable/advanced/functions.html#return-value-policies
py::buffer_protocol
+def_buffer
combo so that way I'd be able to usenp.frombuffer
. Thing is, I want to avoid adding the numpy dependency to the project. Actually, the end goal is being able to pass data efficiently from c++ to functions such as pyopengl.sourceforge.net/documentation/manual-3.0/… . At a first glance, I think the memoryview approach is exactly what I'm looking for here... I'll give it a shot the next coming days to see how it performs ;) – BPL