如何使用 pybind11 通过引用 python 来公开修改数据的 c++ 函数?

How to expose c++ function modifying data by reference to python using pybind11?

提问人:Hossam Alzomor 提问时间:6/24/2022 更新时间:9/7/2023 访问量:300

问:

我正在使用 pybind11 创建 c++ 库的 python 接口, 其中一个函数接收指向 char 数组的指针并更新其值 , 问题是 char 数组的值在 C++ 代码中发生了变化,但在从 C++ 函数调用返回后没有改变,如下一段代码所示。

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;
}

我使用以下 pybind11 代码将函数暴露给 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");
}

并使用以下 python 进行测试

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

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

问题是“obj.string”的值在C++代码中被接收和更改 但是当我在python中调用函数后检查它时,我发现初始值没有修改,如下代码所示。

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

我发现了一些其他工作,建议实现 c++ 包装器或从 python 传递 ctype 变量。

那么如何从python代码中引用c++函数来传递对象呢?

Python C++ 按引用传递

评论

0赞 Davis Herring 6/25/2022
如果您直接拥有 Python 的缓冲区,那不会溢出缓冲区吗?strcpy"ABC"
0赞 Hossam Alzomor 6/27/2022
@DavisHerring这个问题对我来说并不清楚
0赞 Davis Herring 6/27/2022
您正在尝试将 17 个字符复制到 3 个字符的字符串中。
0赞 Hossam Alzomor 6/28/2022
@DavisHerring我认为问题与数据大小无关,但我在 python 中使用初始化“sring”vriable 进行了测试,其字符数比在 C++ 库中复制的字符更多。但我得到相同的结果,在 C++ 库内复制的数据只能在 C++ 函数中显示,但是从 C++ 调用返回后,“string”的内容是用于在 python 中初始化变量的旧值。
0赞 Davis Herring 6/28/2022
这不是重点:这种修改 Python 数据的风格无法有效,因此没有必要研究如何使其在有限的意义上工作。

答:

1赞 Davis Herring 9/7/2023 #1

您无法修改 Python 字符串,因此您必须返回一个新对象。(您可以通过将原始字符串复制到缓冲区中,然后由 C++ 函数修改该缓冲区 - 在检查其长度是否完全正确之后!str

(从技术上讲,从 C/C++ 你可以修改 Python 字符串,但不能修改它的长度,如果你不小心使用它,它会破坏很多东西。