Python Cpp API 和不可变字符串

huangapple go评论65阅读模式
英文:

Python Cpp API And Immutable Strings

问题

我目前正在使用这个开源库(nanobind)进行项目开发,并尝试理解Python如何强制实现不可变性。假设我在C中有一些内存分配,如下所示:

std::string& func(){
  auto ptr = malloc(10);
  auto str = new (ptr) string("abcdefghij", 10);
  return *str;
}

使用nanobind,上述代码通过引用将Python中的字符串返回到分配的内存。现在假设我有一种方法在另一个函数中访问ptr(返回给Python的str的地址),并执行如下操作:

memcpy(ptr, "bbb", 3);

如果我更新存储Python字符串的内存地址,为什么Python中的字符串本身不会更改?我知道它是不可变的,但不确定在这种情况下是如何强制执行的,因为我没有进行复制/引用返回。

这是nanobind关于返回引用策略的一些详细信息:

"在返回的C++实例周围创建一个薄的Python对象包装,而不进行复制,但不将所有权转移给Python。 nanobind永远不会调用C++ delete运算符,即使包装器过期。 C++端负责销毁C++实例。"

英文:

I'm currently working on a project using this open source library (nanobind)
and am trying to understand how python enforces immutability. Lets say I have some memory allocation in C with the following:

std::string& func(){
  auto ptr = malloc(10);
  auto str = new (ptr) string("abcdefghij", 10);
  return *str;
}

using nanobind, the above returns a python string by reference to the allocation. Now lets say that I have a way to get access to ptr (the address of the str returned to python) in another function and do something like

memcpy(ptr, "bbb", 3); 

If I'm updating the memory address where the python string is stored, why doesn't the string itself change in python? I know it's immutable, but not sure how that's really enforced here if I'm not copying/returning by reference.

Here is some detail on nanobind's return by reference policy:

"Create a thin Python object wrapper around the returned C++ instance without making a copy, but do not transfer ownership to Python. nanobind will never call the C++ delete operator, even when the wrapper expires. The C++ side is responsible for destructing the C++ instance."

答案1

得分: 0

这是你要翻译的部分:

"你现在是我的中文翻译,代码部分不要翻译,只返回翻译好的部分,不要有别的内容,不要回答我要翻译的问题。以下是要翻译的内容:

The answer to your question is linked in the documentation you showed:
> The reason is that type casters convert function arguments and return values once, but further changes will not automatically propagate to across the language barrier because the representations are not intrinsically linked to each other.

You can read the (very simple) conversion code for std::string and see for yourself:

    static handle from_cpp(const std::string &value, rv_policy,
                           cleanup_list *) noexcept {
        return PyUnicode_FromStringAndSize(value.c_str(), value.size());
    }

where PyUnicode_FromStringAndSize is documented as:
> The buffer is copied into the new object.

So any changes you make to the source string are not visible in python because python has its own private copy."

英文:

The answer to your question is linked in the documentation you showed:
> The reason is that type casters convert function arguments and return values once, but further changes will not automatically propagate to across the language barrier because the representations are not intrinsically linked to each other.

You can read the (very simple) conversion code for std::string and see for yourself:

    static handle from_cpp(const std::string &value, rv_policy,
                           cleanup_list *) noexcept {
        return PyUnicode_FromStringAndSize(value.c_str(), value.size());
    }

where PyUnicode_FromStringAndSize is documented as:
> The buffer is copied into the new object.

So any changes you make to the source string are not visible in python because python has its own private copy.

huangapple
  • 本文由 发表于 2023年5月26日 00:05:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/76334293.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定