【发布时间】:2009-04-16 08:04:34
【问题描述】:
我有一个 COM API foo,IDL 看起来像:
foo([in] unsigned long ulSize, [in, size_is(ulSize)] unsigned char* pData)
当我使用foo(0,NULL); 使用此功能时
我收到一个错误 - NULL 参数传递。有没有办法解决这个问题?
【问题讨论】:
我有一个 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);
【讨论】:
不要在 COM API 中使用 char* —— 改用 BSTR。然后传递一个空字符串。
foo([in] unsigned long ulSize, [in] BSTR pData)
...
foo(1, _bstr_t(""));
【讨论】:
您可能应该将 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 接口可能更合适。或者可能有一些其他的技巧来传输数据,您可以编写自定义的军事方法来序列化和反序列化内容。
【讨论】:
如果您要传递 BSTR,您应该只传递 BSTR 值 - 它们已经计算了长度(使用 SysStrLength 来查找长度)。
如果你想传入一个以 null 结尾的字符串,请使用 Greg 所说的 [string] 属性
但您的实际问题的答案是您需要将字符串参数标记为“唯一” - 这让 MIDL 编译器(和 RPC 运行时库)知道该参数可以为 NULL。
所以使用:
foo([in, string] unsigned char* pData)
您不需要长度字段,因为它是一个以 null 结尾的字符串 - 因此您可以在字符串上使用 strlen。
【讨论】:
foo 大概是这样实现的:
HRESULT foo(unsigned long ulSize, unsigned char* pData) {
if (!pData) {
return E_POINTER;
}
...
}
在这种情况下,唯一的解决方法是传递非 NULL pData。
【讨论】: