简体   繁体   English

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

[英]Convention for passing BSTRs into COM functions from C# (COM interop)

I am writing writing an API in COM in C++, and also writing a program which consumes this API in C#. 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.我的问题是关于将 BSTR 传递到 COM 函数时的 BSTR memory 管理语义。 Say my IDL looks like:假设我的 IDL 看起来像:

HRESULT SomeFunction([in] BSTR input);

Currently this function is implemented like this:目前这个 function 是这样实现的:

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):当我从 C# 用SomeFunction(myString)之类的东西调用它时, C# 会生成类似这样的东西(伪代码):

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?也就是说,C# 是否释放它生成的 BSTR 以编组到 COM 接口,还是应该在我的 function 中释放它? Thanks!谢谢!

From Allocating and Releasing Memory for a BSTR :为 BSTR 分配和释放 Memory

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.当您调用需要BSTR参数的 function 时,您必须在调用之前为BSTR分配 memory 并在之后释放它。 ... ...

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. 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?否则,COM object 怎么知道它是从 C# 或其他一些语言运行时调用的?

Additional google-fu turned up this: Marshaling between Managed and Unmanaged Code额外的 google-fu 出现了这个:托管和非托管代码之间的编组

... Regarding ownership issues, the CLR follows COM-style conventions: ...关于所有权问题,CLR 遵循 COM 风格的约定:

  • Memory passed as [in] is owned by the caller and should be both作为 [in] 传递的 Memory 归调用者所有,并且应该是
    allocated by the caller and freed by the caller.由调用者分配并由调用者释放。 The callee should被调用者应该
    not try to free or modify that memory.不要尝试释放或修改 memory。
  • Memory allocated by the callee and passed as [out] or returned is owned by the caller and should be freed by the caller. Memory 由被调用者分配并作为 [out] 传递或返回,归调用者所有,应由调用者释放。
  • 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.被调用者可以释放从调用者以 [in, out] 传递的 memory,为其分配新的 memory,并覆盖旧指针值,从而将其传递出去。 The new memory is owned by the caller.新的 memory 归调用者所有。 This requires two levels of indirection, such as char **.这需要两级间接,例如 char **。

In the interop world, caller/callee becomes CLR/native code.在互操作世界中,调用者/被调用者成为 CLR/本机代码。 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从 [out] 接收指向 memory 块的指针
the CLR, you need to free it. CLR,你需要释放它。 On the other hand, if the CLR receives另一方面,如果 CLR 收到
a pointer that is passed as [out] from native code, the CLR needs to从本机代码作为 [out] 传递的指针,CLR 需要
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.因此 CLR 遵循 memory 所有权的 COM 规则。 QED. QED。

Do you mean from the point of view of the C# developer or from the C++ developer.您的意思是从 C# 开发人员的角度还是从 C++ 开发人员的角度来看。

The C# developer should not have to worry about any memory management when dealing with COM+. C# 开发人员在处理 COM+ 时不必担心任何 memory 管理。

Creating a COM+ component in C++, you would not have to know who is calling you, the memory semantics are the same.在 C++ 中创建 COM+ 组件,您不必知道是谁在呼叫您,memory 语义相同。 If it's an in parameter, the caller is responsible for managing the memory, regardless of whether it's C++ or C#.如果是in参数,则调用者负责管理memory,无论是C++还是C#。 In C#, the CLR takes care of it for them.在 C# 中,CLR 会为他们处理。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM