gpt4 book ai didi

.net - 从结构句柄的 System::String^ 成员编码到 std::string

转载 作者:行者123 更新时间:2023-12-02 04:34:31 27 4
gpt4 key购买 nike

我正在尝试从 System::String^ 编码到 std::string。

通常这可以通过 marshal_as<T> 来完成模板即

System::String ^managedString = "test";
std::string stdString = marshal_as<std::string>(managedString);

但是如果 String^ 是通过引用访问的结构的一部分,即

value struct SomeStruct {
String ^managedString;
};

auto structHandle = gcnew SomeStruct();
structHandle->managedString = "test";
std::string stdString = marshal_as<std::string>(structHandle->managedString);

编译器会抛出以下错误

error C2665: 'msclr::interop::marshal_as' : none of the 3 overloads could convert all the argument types

但是,如果该结构不是句柄,而是实际的结构,则它可以正常工作。

最佳答案

   auto structHandle = gcnew SomeStruct();

这就是问题开始的地方。 structHandle 引用指向 SomeStruct 的装箱 副本。它需要装箱,因为 SomeStruct 是一个值类型,该结构的副本存储在 GC 堆上。

您尝试使用的 marshal_as<> 重载的签名是:

   marshal_as<std::string,System::String^>(System::String ^const &)

const&问题是,您无法获得对该成员的非托管引用,它的地址不稳定(不是 const),因为垃圾收集器可以在执行 marshal_as<> 时移动该对象。当 marshal_as 现在取消引用不再存在的对象时,这会导致灾难。

解决方法是在尝试转换之前将引用从装箱对象中复制出来:

   structHandle->managedString = "test";
String^ refCopy = structHandle->managedString;
std::string stdString = marshal_as<std::string>(refCopy); // fine

但这只是针对代码中实际问题的一种破解。值类型的存在是为了提高代码效率,允许将结构存储在堆栈帧或 CPU 寄存器上。就像 native C++ 对象一样。通过对结构进行装箱,您将放弃这一优势。或者换句话说,声明 value struct 没有任何意义。如果您不打算将其视为一种值(value)。正确使用它来进行正确的修复:

    SomeStruct value;
value.managedString = "test";
auto result = marshal_as<std::string>(value.managedString); // fine

或者,如果您通过在函数参数上错误地使用 ^ 来获取引用,则重写为:

    void SomeFunction(SomeStruct% arg) {
auto nativeString = marshal_as<std::string>(arg.managedString);
'' etc..
}

请注意使用 % 而不是 ^ 通过引用传递变量。但不要这样做,值类型的要点是复制值比取消引用指针来获取值更便宜。确保您的值类型不要太大,字段不应超过 4 个。如果它更大,那么您应该使用引用类型。

关于.net - 从结构句柄的 System::String^ 成员编码到 std::string,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30529869/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com