如何调用一个从c#中获取指向BSTR指针的COM方法

本文关键字:取指 获取 BSTR 指针 COM 方法 调用 何调用 一个 | 更新日期: 2023-09-27 18:16:27

我试图从c#中调用以下"foo" COM方法:

interface IFoo : public IUnknown
{
    virtual HRESULT __stdcall foo( BSTR * log ) = 0;
}

在c#中是这样声明的:

[ComImport, Guid( "98D93A58-2889-43a5-A182-47DEE781D41E" ),
 InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]
public interface IFoo
{
    void foo( out string log );
}

在c#中是这样调用的:(x是实现IFoo的COM类的一个实例)

string log;
x.foo( out log );

当我运行这段代码时,我得到以下异常:

System.Runtime.InteropServices.MarshalDirectiveException was unhandled
  Message=Marshaler restriction: Excessively long string.

我做错了什么?

顺便说一下,如果我在c++中像这样调用"foo",下面的代码就能正常工作:
CComBSTR log;
pX->foo( &log );

如何调用一个从c#中获取指向BSTR指针的COM方法

您应该使用ref说明符。请参阅字符串的默认封送处理,特别是PassStringRef1和PassStringRef2中的示例。

The following example shows strings declared in the IStringWorker interface.
Visual C++
public interface IStringWorker {
void PassString1(String s);
void PassString2([MarshalAs(UnmanagedType.BStr)]String s);
void PassString3([MarshalAs(UnmanagedType.LPStr)]String s);
void PassString4([MarshalAs(UnmanagedType.LPWStr)]String s);
void PassStringRef1(ref String s);
void PassStringRef2([MarshalAs(UnmanagedType.BStr)]ref String s);
void PassStringRef3([MarshalAs(UnmanagedType.LPStr)]ref String s);
void PassStringRef4([MarshalAs(UnmanagedType.LPWStr)]ref String s);
);
The following example shows the corresponding interface described in a type library.
[…]
interface IStringWorker : IDispatch {
HRESULT PassString1([in] BSTR s);
HRESULT PassString2([in] BSTR s);
HRESULT PassString3([in] LPStr s);
HRESULT PassString4([in] LPWStr s);
HRESULT PassStringRef1([in, out] BSTR *s);
HRESULT PassStringRef2([in, out] BSTR *s);
HRESULT PassStringRef3([in, out] LPStr *s);
HRESULT PassStringRef4([in, out] LPWStr *s);
);