2

Platform::StringReference存在,以便您可以将 aconst wchar_t*跨 ABI 边界传递给接受 a 的函数String^而无需复制。StringReference隐式转换为 a ,String^其内部指针与原始const wchar_t*. 这由以下代码验证;如果您逐步浏览它,您会发现pz == z

void param(String^ s)
{
    const wchar_t* z = s->Data();
}

App::App()
{
    std::wstring p = L"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz";
    const wchar_t* pz = p.c_str();
    param(StringReference(pz));
}

但是,尝试返回 aStringReference似乎并没有以同样的方式工作,我很好奇为什么。如果我有一个返回的函数String^并从中返回 a StringReference,则调用相同的隐式转换运算符,但是当调用者获取它们时,String^它具有包含副本的不同内部数据指针。这是一些尝试它的代码:

String^ ret()
{
    std::wstring s = L"12345678901234567890123456789012345678901234567890";
    const wchar_t* z = s.c_str();
    return StringReference(z);
}

App::App()
{
    String^ r = ret();
    const wchar_t* rz = r->Data();
}

该代码以两种方式进行验证:首先,如果您逐步执行,您会发现它z != rz,其次,r最终指向一个有效字符串而不是垃圾,因此必须制作一个副本,因为原始字符串在ret.

我也尝试通过 out 参数返回,但我得到与直接返回相同的结果(z != ozo以有效字符串结束):

void out(String^* r)
{
    std::wstring s = L"12345678901234567890123456789012345678901234567890";
    const wchar_t* z = s.c_str();
    *r = StringReference(z);
}

App::App()
{
    String^ o;
    out(&o);
    const wchar_t* oz = o->Data();
}

有没有一种方法可以像StringReference通过 ABI 边界一样返回一个?我想这种行为将取决于调用者的语言以及该语言如何从 WinRT 编组字符串,但似乎至少 C++/CX 调用者应该能够做到这一点。

4

1 回答 1

4

不,您不能跨 ABI 边界返回 StringReference。跨 ABI 边界返回 StringReference 与返回局部变量的地址类似(但不相同)。这是因为 StringReference 的全部意义在于 StringReference 不分配任何新内存。

考虑如果您可以跨 ABI 边界返回 StringReference 会发生什么。如果你有会发生什么:

String^ ReturnAString()
{
    const wchar_t buffer[500] = "MyString";
    return StringReference(buffer);
}

StringReference只是分配的堆栈的包装器buffer。显然,您不能在 ABI 边界上返回它(一旦例程退出,堆栈存储就会被回收)。

相反,您需要返回一个真实的 Platform::String - Platform::String 包含字符串数据的副本,因此可以安全地将其返回给调用者。

于 2013-07-18T17:31:19.807 回答