Hossein
Hossein

Reputation: 25924

How is it possible to access a Python object using Pybind11 in a C callback?

I have a C++ DLL that embeds python interpreter using Pybin11. The Python side of the project accepts callbacks and passes some arguments to them. The callbacks then are executed on the C++/C/C# etc part. On C++ side I can freely use pybind11::object can handle complex types such as OpenCV images (using py::array_t for example); however, when it comes to exposing it to the C which can be then used for variety of languages including C#, I fail.

The reason I fail, is that I can't simply cast the py::object to a type that C understands and vice versa. for example, I can't simply change my C++ callback which is :

typedef void(*CallbackFn)(bool, std::string, py::array_t<uint8_t>&);

void default_callback(bool status, std::string id, py::array_t<uint8_t>& img)
{
    auto rows = img.shape(0);
    auto cols = img.shape(1);
    auto type = CV_8UC3;
    cv::Mat img1(rows, cols, type, img.mutable_data());
   ...

}

to its C compatible variant :

typedef void(*CallbackFn)(bool, char*, void*);
void default_callback(bool status, char* id, void* img)
{
    //cast the void* into something useful
    ...
}

This simply causes an exception on Python side which simply says,

TypeError: (): incompatible function arguments. The following argument types are supported:
    1. (arg0: bool, arg1: str, arg2: capsule) -> None

Invoked with: True, '5', array([[[195, 216, 239],
        [194, 215, 237],
        [193, 214, 236],
        ...,
        [ 98, 108, 143],
        [100, 110, 147],
        [101, 111, 149]]], dtype=uint8)

using other objects (for example on an opencv img.data I get errors such as this :

TypeError: (): incompatible function arguments. The following argument types are supported:
    1. (arg0: bool, arg1: str, arg2: capsule) -> None

Invoked with: True, '5', <memory at 0x0000021BC3433D68>

So my question is, how should I go about this, so that I don't get an exception on Python part? How can I access to an object pointer in Python? is it even possible?

Upvotes: 3

Views: 590

Answers (1)

Hossein
Hossein

Reputation: 25924

This seems like a Pybind11 bug and creating an issue on Pybind11 didn't help, so I ended up using a delegate callback. That is use a middle callback for converting between the two format. I explained this in detail in my previous (related) question.

Upvotes: 1

Related Questions