【问题标题】:COM API - could not pass "NULL" for a pointer argumentCOM API - 无法为指针参数传递“NULL”
【发布时间】: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 参数传递。有没有办法解决这个问题?

【问题讨论】:

    标签: c++ winapi com midl


    【解决方案1】:

    您是否尝试过传递一个空字符串?

    unsigned char Data = 0;
    foo(0,&Data);
    

    【讨论】:

      【解决方案2】:

      不要在 COM API 中使用 char* —— 改用 BSTR。然后传递一个空字符串。

      foo([in] unsigned long ulSize, [in] BSTR pData)
      
      ...
      
      foo(1, _bstr_t(""));
      

      【讨论】:

      • 我实际上想传递一个 void* 类型的结构,因为 IDL 中没有 void*,我使用的是 char*。
      • @null:通过 COM 接口传递 void* 充满危险。一方面,COM 不知道如何编组 void* 指向的数据,另一方面,指针在调用的另一端可能无效。你真的不应该这样做。
      • 如果调用正在进行中,则传递 (void *) 不会比以往任何时候都危险。双方必须对指向的数据类型有相同的定义,但没有其他要求,因为它是COM。
      【解决方案3】:

      您可能应该将 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 接口可能更合适。或者可能有一些其他的技巧来传输数据,您可以编写自定义的军事方法来序列化和反序列化内容。

      【讨论】:

      • 它实际上是 void* 类型,因为 IDL 中没有 void*,而是使用 char*。
      【解决方案4】:

      如果您要传递 BSTR,您应该只传递 BSTR 值 - 它们已经计算了长度(使用 SysStrLength 来查找长度)。

      如果你想传入一个以 null 结尾的字符串,请使用 Greg 所说的 [string] 属性

      但您的实际问题的答案是您需要将字符串参数标记为“唯一” - 这让 MIDL 编译器(和 RPC 运行时库)知道该参数可以为 NULL。

      所以使用:

      foo([in, string] unsigned char* pData)
      

      您不需要长度字段,因为它是一个以 null 结尾的字符串 - 因此您可以在字符串上使用 strlen

      【讨论】:

        【解决方案5】:

        foo 大概是这样实现的:

        HRESULT foo(unsigned long ulSize, unsigned char* pData) {
          if (!pData) {
            return E_POINTER;
          }
          ...
        }
        

        在这种情况下,唯一的解决方法是传递非 NULL pData。

        【讨论】:

          猜你喜欢
          • 2011-12-23
          • 1970-01-01
          • 1970-01-01
          • 2012-01-24
          • 1970-01-01
          • 2011-12-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多