0

我在 WinRT 组件中有一个 ref 类:

namespace WinRTComponent
{
    public ref class Class1 sealed
    {
    public:
        Class1();

        void MyMethod(wchar_t* wcharPtr)
        {
            // Do nothing.
        }
    };
}

我还有一个 Windows Store C++ XAML 应用程序,它引用了 WinRT 组件。在我的应用程序中,我运行以下代码:

std::wstring str = L"Some text.";
const wchar_t* strPtr = str.data();

WinRTComponent::Class1^ class1 = ref new WinRTComponent::Class1();

wchar_t firstCharBefore = strPtr[0]; // It is 'S', correctly.

class1->MyMethod(const_cast<wchar_t*>(strPtr));

wchar_t firstCharAfter = strPtr[0]; // It is 0! Why?

当我将 wchar_t* 指针传递给 WinRT 组件的公共方法时,字符串的第一个字符被删除并更改为 0。

这是什么原因?这是预期的行为还是错误?

4

1 回答 1

2

我认为这是因为 avoid MyMethod(wchar_t* wcharPtr)上的公共方法ref class不是接受输入字符串的函数,而是具有wchar_tout 参数的函数。换句话说,WinRTMyMethod是一个返回 16 位字符的函数。所以我的猜测是,WinRT ABI 机器要么在将值赋给之前将其清空MyMethod,要么检测到您的实现MyMethod从未分配给它并生成为其分配默认值的代码。

ref class关键要点是平均输出的公共方法上的指针参数,而不是指针输入。指针不能跨越 ABI 边界,只有 WinRT 类型可以。C++ 类型wchar_t映射到 WinRT 16 位字符类型所以没关系,指针参数是 C++/CX 实现 WinRT 输出参数的方式,因为这是 C++ 通过参数返回数据的最自然的方式。

要在 C++/CX 中编写一个接受字符串输入值的组件的公共方法,您必须将其Platform::String^用作参数类型。如果你从 C++/CX 调用这个函数,你可以通过传递一个来避免复制StringReference

WinRTComponent::Class1^ class1 = ref new WinRTComponent::Class1();
class1->MyMethod(Platform::StringReference(strPtr));

如果你这样做了,你会发现Data()String^内部调用MyMethod会得到和strPtr传入一样的结果。

有关它的更多信息,请参阅C++/CX 字符串文档的“StringReference”部分。

于 2013-07-18T15:44:09.593 回答