MIDL 3.0 数组参数的反向 C++/WinRT ABI 参数顺序?
Reverse C++/WinRT ABI parameter order for MIDL 3.0 array parameter?
我有一个现有接口,我正尝试使用 MIDL 3.0 定义它。其中一种方法具有此 C++ 签名:
HRESULT GetArray(struct FOO** outArray, uint32_t* outSize);
我试过像这样将它翻译成 IDL:
namespace Examples {
struct Foo {
Int32 n1;
Int32 n2;
};
interface IExample {
void GetArray(out Foo[] array);
}
}
但是,生成的 C++/WinRT ABI 具有相反顺序的参数:
template <> struct abi<Examples::IExample>{ struct type : IInspectable
{
virtual HRESULT __stdcall GetArray(uint32_t* __arraySize, struct struct_Examples_Foo** array) noexcept = 0;
};};
考虑到 recommended order,这确实有意义。不幸的是,我没有能力改变现有接口的参数顺序。相反,我认为我可以使用 "classic" 样式来解决它:
namespace Examples {
[uuid("d7675bdc-7b6e-4936-a4a0-f113c1a3ef70"), version(1)]
interface IExample {
HRESULT GetArray(
[out, size_is(, *size)] Foo** array,
[out] unsigned long* size
);
}
}
但是,这被 MIDL 编译器拒绝了:
MIDL4058: [msg]The size parameter of an array parameter must appear directly before the array parameter. [context]size
如何在 IDL 中以产生正确 ABI 的方式编写此接口?
WinRT 对数组参数的排序有严格的 ABI 定义,正如您所发现的那样,它是 (size, pointer)
而不是相反。没有办法改变这一点,因为所有投影(例如 .NET、JavaScript 和 C++/CX)都期望这个顺序,如果以错误的顺序传递,将会灾难性地失败。
如果您不能更改顺序,您能否编写一个包装器 class 来公开正确的顺序并简单地将调用转发到您现有的代码并反转参数?
如果做不到这一点,如果您只关心 C++(可能还有 C# 客户端),还有另一种方法可以支持这一点。也就是说,您可以定义 classic-COM 接口并让您的 WinRT 对象也实现该接口,而不是为此方法定义 WinRT 接口。然后您的 WinRT 对象 QI 的客户端针对该 COM 接口并可以按您需要的顺序传递参数。
我有一个现有接口,我正尝试使用 MIDL 3.0 定义它。其中一种方法具有此 C++ 签名:
HRESULT GetArray(struct FOO** outArray, uint32_t* outSize);
我试过像这样将它翻译成 IDL:
namespace Examples {
struct Foo {
Int32 n1;
Int32 n2;
};
interface IExample {
void GetArray(out Foo[] array);
}
}
但是,生成的 C++/WinRT ABI 具有相反顺序的参数:
template <> struct abi<Examples::IExample>{ struct type : IInspectable
{
virtual HRESULT __stdcall GetArray(uint32_t* __arraySize, struct struct_Examples_Foo** array) noexcept = 0;
};};
考虑到 recommended order,这确实有意义。不幸的是,我没有能力改变现有接口的参数顺序。相反,我认为我可以使用 "classic" 样式来解决它:
namespace Examples {
[uuid("d7675bdc-7b6e-4936-a4a0-f113c1a3ef70"), version(1)]
interface IExample {
HRESULT GetArray(
[out, size_is(, *size)] Foo** array,
[out] unsigned long* size
);
}
}
但是,这被 MIDL 编译器拒绝了:
MIDL4058: [msg]The size parameter of an array parameter must appear directly before the array parameter. [context]size
如何在 IDL 中以产生正确 ABI 的方式编写此接口?
WinRT 对数组参数的排序有严格的 ABI 定义,正如您所发现的那样,它是 (size, pointer)
而不是相反。没有办法改变这一点,因为所有投影(例如 .NET、JavaScript 和 C++/CX)都期望这个顺序,如果以错误的顺序传递,将会灾难性地失败。
如果您不能更改顺序,您能否编写一个包装器 class 来公开正确的顺序并简单地将调用转发到您现有的代码并反转参数?
如果做不到这一点,如果您只关心 C++(可能还有 C# 客户端),还有另一种方法可以支持这一点。也就是说,您可以定义 classic-COM 接口并让您的 WinRT 对象也实现该接口,而不是为此方法定义 WinRT 接口。然后您的 WinRT 对象 QI 的客户端针对该 COM 接口并可以按您需要的顺序传递参数。