如何公开C++功能通过使用Pybind11引用Python来修改数据?

发布于 2025-02-10 19:51:33 字数 1185 浏览 1 评论 0原文

我正在使用pybind11创建一个python接口到C ++库, 其中一个功能接收到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)

。 但是,当我在python中调用功能后检查它时,我发现初始值不会如下一个代码所示进行修改。

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

我发现了一些围绕提议实施C ++包装器或通过Python传递CTYPE变量的工作。

如何通过引用Python代码的C ++函数传递对象?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

好听的两个字的网名 2025-02-17 19:51:33

您无法修改Python字符串,因此您必须返回 new str对象。 (您可以通过将原始字符串复制到一个缓冲区中,然后由C ++函数修改,然后检查它是恰好是 正确的长度!)

(从技术上讲,从c/c ++中,您可以修改python字符串,但不会长度,如果您在不尽最大的谨慎态度的情况下使用它,它将破坏很多东西。)

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.)

提赋 2025-02-17 19:51:33

对于基本数据类型,例如intdoublefloat,您可以用lambda函数中的参考类型包装该功能并返回它们。
假设您具有C ++函数,具有参考的参数如下,

void plus_one_inplace(int &i) { i++; }

您可以在Pybind中使用lambda函数绑定它

PYBIND11_MODULE(_core, m) {
    m.def("plus_one_inplace", [](int i){plus_one_inplace(i); return i;}, "add one inplace");
}

,而import _core in python中

import _core
i = 1
i = m.plus_one_inplace(i)
i

,然后您将获得i = 2

由于int是python中不变的类型,因此您需要包装lambda功能并返回值。

将参考类型从int扩展到vector,您可以尝试使用pybind中的不透明,以避免不必要的复制移动,这是一个使用vector&lt; char&gt;模拟char*char*的示例

void concat(std::vector<char>& s1, const std::vector<char>& s2) {
    s1.insert(s1.end(), s2.begin(), s2.end());
}

。可以按照以下方式绑定,

#include<pybind11/stl.h>
#include <pybind11/stl_bind.h>
PYBIND11_MAKE_OPAQUE(std::vector<char>);

PYBIND11_MODULE(_core, m) {
      py::bind_vector<std::vector<char>>(m, "VectorChar");
      m.def("concat", &concat, "s1"_a, "s2"_a);
}

您可以在Python中导入_Core

>>> import two_center_integral as m
>>> s1 = m.VectorChar("hello")
>>> s2 = m.VectorChar("world")
>>> m.concat(s1, s2)
>>> s1
VectorChar[h, e, l, l, o, w, o, r, l, d]
>>> ''.join(s1)
'helloworld'

并参见s1已传递为参考。

参考:

  1. https> https:https://pybind11.Read11.Readthedocs。 io/en/stable/Advanced/cast/stl.html#binding-stl-containers
  2. https://github.com/pybind/pybind11/issues/134

For basic data types, such as int, double, float, you can wrap the function with reference type in a lambda function and return them.
Suppose you have a c++ function with arguments by reference as follows,

void plus_one_inplace(int &i) { i++; }

you can bind it with lambda function in pybind like this

PYBIND11_MODULE(_core, m) {
    m.def("plus_one_inplace", [](int i){plus_one_inplace(i); return i;}, "add one inplace");
}

and import _core in python

import _core
i = 1
i = m.plus_one_inplace(i)
i

and then you will get i=2.

As ints are immutable types in python so you need to wrap in lambda function and return value.

Extend reference type from int to vector, you may try opaque in pybind to avoid unnecessary copy movement, here is an example to use vector<char> to simulate char*

void concat(std::vector<char>& s1, const std::vector<char>& s2) {
    s1.insert(s1.end(), s2.begin(), s2.end());
}

then you can bind as follows

#include<pybind11/stl.h>
#include <pybind11/stl_bind.h>
PYBIND11_MAKE_OPAQUE(std::vector<char>);

PYBIND11_MODULE(_core, m) {
      py::bind_vector<std::vector<char>>(m, "VectorChar");
      m.def("concat", &concat, "s1"_a, "s2"_a);
}

you can import _core in python like this,

>>> import two_center_integral as m
>>> s1 = m.VectorChar("hello")
>>> s2 = m.VectorChar("world")
>>> m.concat(s1, s2)
>>> s1
VectorChar[h, e, l, l, o, w, o, r, l, d]
>>> ''.join(s1)
'helloworld'

and see s1 has been passed as reference.

Reference:

  1. https://pybind11.readthedocs.io/en/stable/advanced/cast/stl.html#binding-stl-containers
  2. https://github.com/pybind/pybind11/issues/134
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文