google / flatbuffers

FlatBuffers: Memory Efficient Serialization Library
https://flatbuffers.dev/
Apache License 2.0
23.28k stars 3.25k forks source link

Retrieve flatbuffer via pointer #4215

Closed perara closed 7 years ago

perara commented 7 years ago

What i want is to retreive a buffer made in C++ in Python (Via memory) I'm trying to retrieve a buffer from memory which were created in C++. Basically i created a flatbuffer the following way in C++:

PyObject* PyAPI::registry_hook(PyObject* self, PyObject* args)
{

    std::cout << "Register PyAI with id: " << std::to_string(1337) << std::endl;

    // Create buffer
    flatbuffers::FlatBufferBuilder *fbb = new flatbuffers::FlatBufferBuilder();
    auto state_ptr = State::CreateGame(*fbb);
    fbb->Finish(state_ptr);

    // Get object back from buffer and set random value for debug 
    State::Game *g = State::GetMutableGame(fbb->GetCurrentBufferPointer());
    g->mutate_ticks(1337);

    // Retrieve flatbuffer pointer offset
    uint8_t *bufPtr = fbb->GetBufferPointer();

    // Capsulate flatbuffer pointer into an PyObject. this ensure that the pointer type is preserved when retrieving in python
    PyObject * buffer_capsule_ptr = PyCapsule_New((void *)bufPtr, "X_C_API", NULL);

    return buffer_capsule_ptr;;
}

What the above function does (C++) is:

  1. Create new buffer
  2. Save
  3. Retrieve and set some random value (for debug)
  4. Encapsulate pointer to a PyObject

Then in python:

# Define PyCapsule constraints
ctypes.pythonapi.PyCapsule_GetPointer.restype = ctypes.c_void_p
ctypes.pythonapi.PyCapsule_GetPointer.argtypes = [ctypes.py_object, ctypes.c_char_p]
ctypes.pythonapi.PyCapsule_GetName.restype = ctypes.c_char_p
ctypes.pythonapi.PyCapsule_GetName.argtypes = [ctypes.py_object]

# Retrieve pointer offset
flatbuffer_offset = ctypes.pythonapi.PyCapsule_GetPointer(self.api_id, ctypes.pythonapi.PyCapsule_GetName(self.api_id))

# Set offset to self
self.flatbuffer_offset = flatbuffer_offset

# NOW WHAT?? how to i retrieve buffer using the offset?

So my question is how do i actually return the buffer now that i have the offset in python? I have flatbuffer generated files in both C++ and Python but from what i can see Python does not have any methods for retrieving the buffer like in C++ (fbb->GetCurrentBufferPointer()))

Does this work at all? Any idea / Solution?

aardappel commented 7 years ago

I'm not familiar with C++/Python interop, but really all you should have to do is convert the C++ buffer to a Python byte array, at which point you can use the existing API.

Your call to PyCapsule_New only takes a pointer, and not a length, so clearly isn't constructing a byte array, so likely there isn't a way for the Python API to get at the bytes.