将bstr从c#传递到COM函数的约定(COM互操作)
本文关键字:COM 函数 约定 互操作 bstr | 更新日期: 2023-09-27 18:05:24
我正在用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接口,还是我应该在我的函数中释放它?谢谢!
From分配和释放BSTR内存:
当你调用一个需要
BSTR
参数的函数时,你需要必须在调用前为BSTR
分配内存之后释放. ...
所以如果它是一个输入参数,不要释放它。c#(和任何其他使用COM对象的运行时)必须遵守COM约定来管理传入和传出COM对象的内存,因此必须为字符串管理内存,如果它是一个输入参数。否则,COM对象如何知道它是从c#或其他语言运行时调用的?
额外的google-fu发现了这个:托管和非托管代码之间的封送处理
…关于所有权问题,CLR遵循com风格约定:
- 作为[in]传递的内存由调用者拥有,并且应该是
由调用方分配,由调用方释放。被调用者应该
不要试图释放或修改记忆。- 由被调用者分配并作为[out]传递或返回的内存归调用方所有,并且应该由调用方释放。
- 被调用者可以释放从调用者那里传入的[in, out]内存。为它分配新的内存,并覆盖旧的指针值,从而把它传递出去。新的内存由调用者拥有。这需要两层间接,如char **。
在互操作世界中,调用者/被调用者变成了CLR/本机代码。规则上面暗示在未固定的情况下,如果在本机代码中
从
接收一个指向[out]传递给你的内存块的指针CLR,你需要释放它。另一方面,如果CLR接收到
从本机代码作为[out]传递的指针,CLR需要
免费的。显然,在第一种情况下,本机代码需要执行
在第二种情况下,托管代码需要执行
重新分配。
所以CLR遵循COM规则的内存所有权。QED .
您是指从c#开发人员的角度还是从c++开发人员的角度?
c#开发人员在处理COM+时不应该担心任何内存管理。
在c++中创建一个COM+组件,你不必知道是谁在调用你,内存语义是一样的。如果它是一个in参数,调用者负责管理内存,无论它是c++还是c#。在c#中,CLR会为它们处理。