Search code examples
pythonc++pass-by-referencepybind11

How to expose a C++ function modifying data by reference to Python using pybind11?


I am using pybind11 to create a Python interface to a C++ library, one of the functions receives pointer to char array and updates its value , the problem is that the value of the char array is changed in C++ code but is not changed after returning from the C++ function call as shown in the next code.

int Copy_String::ModifyString(char* rxBuf)
{
    cout <<"***C++ Before copy***==>" << rxBuf << endl;
    strcpy(rxBuf, "Data to be copied");
    cout <<"***C++ After copy***==> "<< rxBuf << endl;
    return 0;
}

I use the following pybind11 code to expose the function to Python:

PYBIND11_MODULE(copylib, m)
{
    m.doc() = "test modifying string passed by reference"; 
    py::class_<Copy_String>(m,"Copy_String")
        .def_static("ModifyString", &Copy_String::ModifyString," Modify String passed by reference");
}

and use the following python to test it

import copylib as cp
class String:
    string="ABC"

obj = String()
print(obj.string)
cp.Copy_String.ModifyString(obj.string)
print(obj.string)

The problem is that the value of "obj.string" is received and changed inside the C++ code but when I check it after calling the function in python I found that the initial value is not modified as shown in next code.

ABC
***C++ Before copy***==>ABC
***C++ After copy***==> Data to be copied
ABC

I found some other work around proposing to implement a c++ wrapper or passing ctype variable from python.

How to pass object by reference to c++ function from python code?


Solution

  • You can't modify a Python string, so you have to return a new str object instead. (You do that by copying the original string into a buffer that is then modified by the C++ function—after checking that it's exactly the right length!)

    (Technically, from C/C++ you can modify a Python string, but not its length, and it'll break a lot of things if you use it without the utmost care.)