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

发布于 2024-11-29 10:30:02 字数 671 浏览 1 评论 0原文

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

I am writing writing an API in COM in C++, and also writing a program which consumes this API in C#. My question is about BSTR memory management semantics when passing BSTRs into COM functions. Say my IDL looks like:

HRESULT SomeFunction([in] BSTR input);

Currently this function is implemented like this:

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

When I call it from C# with something like SomeFunction(myString), will C# generate something like this (pseudocode):

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

Or rather like this:

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

That is, does C# free the BSTR that it generates to marshal to the COM interface, or should I free it inside my function? Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

似最初 2024-12-06 10:30:02

来自为 BSTR 分配和释放内存

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

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

其他 google-fu 出现了这个:托管代码和非托管代码之间的封送处理

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

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

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

因此,CLR 遵循 COM 内存所有权规则。量子ED。

From 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. ...

So don't free it if it is an input parameter. C# (and any other runtime that uses COM objects) must respect the COM convention for managing memory pass in and out of COM objects, and must therefore manage the memory for the string if it is an input parameter. Otherwise, how would a COM object know that it is being called from C# or some other language runtime?

Additional google-fu turned up this: 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.

So the CLR follows the COM rules for memory ownership. QED.

爱的十字路口 2024-12-06 10:30:02

您的意思是从 C# 开发人员的角度还是从 C++ 开发人员的角度。

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

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

Do you mean from the point of view of the C# developer or from the C++ developer.

The C# developer should not have to worry about any memory management when dealing with COM+.

Creating a COM+ component in C++, you would not have to know who is calling you, the memory semantics are the same. If it's an in parameter, the caller is responsible for managing the memory, regardless of whether it's C++ or C#. In C#, the CLR takes care of it for them.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文