从BS#传递BSTR到COM函数的惯例(COM互操作)

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

HRESULT SomeFunction([in] BSTR input); 

目前这个function实现如下:

 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接口,还是应该在我的函数中释放它? 谢谢!

从为BSTR分配和释放内存 :

当您调用需要BSTR参数的函数时,必须在调用之前为BSTR分配内存,然后释放它。 …

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

额外的google-fu出现了这个问题: 在托管代码和非托管代码之间进行编组

…关于所有权问题,CLR遵循COM式约定:

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

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

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

你的意思是从C#开发人员或C ++开发人员的角度来看。

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

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