我无法将下面的界面定义从Delphi转换为C#:
IDCDSPFilterInterface = interface(IUnknown)
['{BD78EF46-1809-11D6-A458-EDAE78F1DF12}']
// removed functions thjat are already working
function get_FilterName(Index : integer; out Name : PChar): HRESULT; stdcall;
end;我尝试使用StringBuilder的方式如下:
[ComVisible(true), ComImport, SuppressUnmanagedCodeSecurity,
Guid("BD78EF46-1809-11D6-A458-EDAE78F1DF12"),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IDCDSPFilterInterface : IBaseFilter
{
[PreserveSig]
int get_FilterName(int Index, [MarshalAs(UnmanagedType.LPStr)] StringBuilder Name);
}我尝试使用LPStr、LPWStr (这两种方法都在字符串构建器中提供垃圾字符)和LPTStr,这两种方法都失败了,其中有一条错误消息,表示不允许这种编组组合。
德里采用这种方法的定义是:
function TDCDSPFilter.get_FilterName(Index : integer; out Name : PChar): HRESULT; stdcall;
begin
{$IFDEF EXCEPT_DEBUG}try{$ENDIF}
FcsFilter.Lock;
try
{$IFDEF WITH_INTERNAL_DSP}
Result := S_FALSE;
if (Index < 0) or (Index > fFilters.Count -1) then Exit;
Name := PChar(fFilters.Name[Index]);
Result := S_OK;
{$ELSE}
Result := E_NOTIMPL;
{$ENDIF}
finally
FcsFilter.UnLock;
end;
{$IFDEF EXCEPT_DEBUG} except er('TDCDSPFilter.get_FilterName'); end; {$ENDIF}
end;fFilters.Name声明为:
property Name[Index: integer]: String read GetName;我的所有其他接口方法都能很好地与其他基本类型(in和ref)一起工作,除了这个具有PChar输出的接口。
我得到了S_OK,但是StringBuilder中的字符串是垃圾.
我知道方法是正确调用的,因为如果我传递了错误的索引,我就会得到S_FALSE (就像方法体定义的那样)。
有人能帮忙为Delphi提供适当的编组吗?
发布于 2014-02-10 00:57:05
发布于 2014-02-10 07:28:48
这是一个设计得相当糟糕的接口。这是一个COM接口,所以它应该使用COM字符串BSTR。
但是,C#端必须将PChar作为IntPtr类型的out参数进行封送。宣言应包括:
[PreserveSig]
uint get_FilterName(int Index, out IntPtr Name);然后,可以通过调用Marshal.PtrToStringAnsi或Marshal.PtrToStringUni来恢复字符串,具体取决于字符串的编码。
您不能使用StringBuilder,因为这适用于调用方分配缓冲区的情况。而这不是在这里发生的。
正如我所说,使用COM字符串会更好。代码如下所示:
Delphi
function TDCDSPFilter.get_FilterName(Index: integer;
out Name : WideString): HRESULT; stdcall;C#
[PreserveSig]
uint get_FilterName(
int Index,
[MarshalAs(UnmanagedType.BStr)]
out string Name
);当然,这假设您可以修改接口。很可能你做不到。在这种情况下,您将使用out IntPtr。
https://stackoverflow.com/questions/21666846
复制相似问题