我有一个 COM API foo,IDL 看起来像:
foo([in] unsigned long ulSize, [in, size_is(ulSize)] unsigned char* pData)
当我使用这个函数时,foo(0,NULL);
我得到一个错误 - NULL 参数传递。有没有办法解决这个问题?
您是否尝试过传递一个空字符串?
unsigned char Data = 0;
foo(0,&Data);
您可能应该将 char* 标记为字符串以获得一些编组帮助。
foo([in] unsigned long ulSize, [in,string,size_is(ulSize)] unsigned char* pData)
我们没有在 IDL 中使用 size_is 选项,也许它是在强制解决非 NULL 地址的问题?
foo([in] unsigned long ulSize, [in,string] unsigned char* pData)
我当然会推荐使用 BSTR 或 SAFEARRAY 而不是 char。那么问题将是如何最好地处理这种空情况,可能将其视为空字符串,或者有一个单独的方法。
在 COM 中传递指针是非常糟糕的形式,就像使用共享内存传递指针一样,(可能/可能)远程进程将无法访问内存。因此,COM 试图通过为您军事化实际数据来提供帮助,但如果您将其隐藏在不同的数据类型后面,它就不会正确地军事化数据。例如,使用 wchar_t* 它将创建一个在进程之间可用的系统分配字符串。或者你可以做同样的事情并有一个接口接受一个 bstring 并将 sysallocstring() 的结果传递给它
或许你可以告诉我们更多关于你想要使用的结构,用这种类型的对象扩展com接口可能更合适。或者可能有一些其他的技巧来传输数据,您可以编写自定义的军事方法来序列化和反序列化内容。
不要在 COM API 中使用 char* —— 改用 BSTR。然后传递一个空字符串。
foo([in] unsigned long ulSize, [in] BSTR pData)
...
foo(1, _bstr_t(""));
如果您要传递 BSTR,您应该只传递 BSTR 值 - 它们已经计算了长度(使用 SysStrLength 来查找长度)。
如果您想传入一个以空字符结尾的字符串,请使用 Greg 所说的 [string] 属性
但是您的实际问题的答案是您需要将字符串参数标记为“唯一” - 这让 MIDL 编译器(和 RPC 运行时库)知道该参数可以为 NULL。
所以使用:
foo([in, string] unsigned char* pData)
您不需要长度字段,因为它是一个以空值结尾的字符串 - 因此您可以strlen
在字符串上使用。
foo
可能是这样实现的:
HRESULT foo(unsigned long ulSize, unsigned char* pData) {
if (!pData) {
return E_POINTER;
}
...
}
在这种情况下,唯一的解决方法是传递非 NULL pData。