加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

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

发布时间:2020-12-15 04:05:32 所属栏目:百科 来源:网络整理
导读:我正在C编写一个API,并编写一个在C#中使用这个API的程序.我的问题是关于BSTR内存管理语义,将BSTR传递到COM函数.说我的IDL看起来像: HRESULT SomeFunction([in] BSTR input); 目前这个功能是这样实现的: HRESULT SomeFunction(BSTR input) { // Do stuff ..
我正在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.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读