英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论