将BSTR传递到C#(COM互操作)的COM函数的约定

时间:2011-08-11 21:54:34

标签: c# c++ com com-interop

我正在编写用C ++编写COM的API,还编写一个在C#中使用这个API的程序。我的问题是关于将BSTR传递给COM函数时的BSTR内存管理语义。说我的IDL看起来像:

HRESULT SomeFunction([in] BSTR input);

目前这个功能是这样实现的:

HRESULT SomeFunction(BSTR input) {
    // Do stuff ..., then:
    SysFreeString(input);
}

当我使用类似SomeFunction(myString)之类的C#调用它时,C#会生成类似这样的内容(伪代码):

myString = SysAllocString("string");
SomeFunction(myString);

或者更喜欢这样:

myString = SysAllocString("string");
SomeFunction(myString);
SysFreeString(myString);

也就是说,C#是否释放它生成的BSTR来编组COM接口,还是应该在我的函数中释放它?谢谢!

2 个答案:

答案 0 :(得分:14)

来自Allocating and Releasing Memory for a BSTR

  

当你调用一个需要 BSTR 参数的函数时,你   必须在通话之前为 BSTR 分配内存   之后发布它。 ...

所以如果是输入参数,请不要释放它。 C#(以及使用COM对象的任何其他运行时)必须遵守用于管理内存传入和传出COM对象的COM约定,因此必须管理字符串的内存(如果它是输入参数)。否则,COM对象如何知道它是从C#或其他语言运行库调用的?

其他google-fu出现了这个问题:Marshaling between Managed and Unmanaged Code

  

...关于所有权问题,CLR遵循COM风格   约定:

     
      
  • 作为[in]传递的内存由调用者拥有,并且应该都是
      由呼叫者分配并由呼叫者释放。被叫者应该是   不要试图释放或修改那个记忆。
  •   
  • 被叫方分配的内存,并作为[out]传递或返回   由调用者拥有,应由调用者释放。
  •   
  • 被叫方可以释放作为[in,out]从调用方传递的内存,   为它分配新的内存,并覆盖旧的指针值,   从而将它传递出去。新内存由调用者拥有。这个   需要两个间接级别,例如char **。
  •   
     

在互操作世界中,调用者/被调用者变为CLR /本机代码。规则   以上暗示在未固定的情况下,如果在本机代码中你   收到指向传递给你的内存块的指针,作为[out]   CLR,你需要释放它。另一方面,如果CLR收到了   一个从本机代码传递为[out]的指针,CLR需要为   释放它。显然,在第一种情况下,本机代码需要执行   取消分配,在第二种情况下,托管代码需要执行   解除分配。

因此CLR遵循内存所有权的COM规则。 QED。

答案 1 :(得分:0)

您是从C#开发人员还是从C ++开发人员的角度来看。

在处理COM +时,C#开发人员不必担心任何内存管理。

在C ++中创建COM +组件,您不必知道谁在调用您,内存语义是相同的。如果它是in参数,则调用者负责管理内存,无论它是C ++还是C#。在C#中,CLR为它们负责。