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

我正在C编写一个API,并编写一个在C#中使用这个API的程序.我的问题是关于BSTR内存管理语义,将BSTR传递到COM函数.说我的IDL看起来像:
HRESULT SomeFunction([in] BSTR input);

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

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

当我从C#中用类似SomeFunction(myString)的方法调用它时,C#会生成这样的东西(伪代码):

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

或者更像这样:

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

也就是说,C#是否释放它产生的BSTR,以封送到COM接口,还是应该在我的函数内释放它?谢谢!

解决方法

Allocating and Releasing Memory for a BSTR

When you call into a function that expects a BSTR argument,you
must allocate the memory for the BSTR before the call and
release it afterwards. …

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

额外的google-fu表示:Marshaling between Managed and Unmanaged Code

… Regarding ownership issues,the CLR follows COM-style
conventions:

  • Memory passed as [in] is owned by the caller and should be both
    allocated by the caller and freed by the caller. The callee should
    not try to free or modify that memory.
  • Memory allocated by the callee and passed as [out] or returned
    is owned by the caller and should be freed by the caller.
  • The callee can free memory passed as [in,out] from the caller,
    allocate new memory for it,and overwrite the old pointer value,
    thereby passing it out. The new memory is owned by the caller. This
    requires two levels of indirection,such as char **.

In the interop world,caller/callee becomes CLR/native code. The rules
above imply that in the unpinned case,if when in native code you
receive a pointer to a block of memory passed to you as [out] from
the CLR,you need to free it. On the other hand,if the CLR receives
a pointer that is passed as [out] from native code,the CLR needs to
free it. Clearly,in the first case,native code needs to do the
de-allocation and in the second case,managed code needs to do
de-allocation.

所以CLR遵循用于内存所有权的COM规则. QED.

相关文章

目录简介使用JS互操作使用ClipLazor库创建项目使用方法简单测...
目录简介快速入门安装 NuGet 包实体类User数据库类DbFactory...
本文实现一个简单的配置类,原理比较简单,适用于一些小型项...
C#中Description特性主要用于枚举和属性,方法比较简单,记录...
[TOC] # 原理简介 本文参考[C#/WPF/WinForm/程序实现软件开机...
目录简介获取 HTML 文档解析 HTML 文档测试补充:使用 CSS 选...