C# 当Delphi类型为“时,我使用什么C”参数类型;出PChar”吗;?
我无法将下面的接口定义从Delphi转换为C#: 我已通过以下方式尝试使用StringBuilder:C# 当Delphi类型为“时,我使用什么C”参数类型;出PChar”吗;?,c#,interface,com-interop,delphi,C#,Interface,Com Interop,Delphi,我无法将下面的接口定义从Delphi转换为C#: 我已通过以下方式尝试使用StringBuilder: [ComVisible(true), ComImport, SuppressUnmanagedCodeSecurity, Guid("BD78EF46-1809-11D6-A458-EDAE78F1DF12"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IDCDSPFilterInterface
[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;
我的所有其他接口方法都能很好地与其他基本类型(in和ref)配合使用,除了这个带有PChar输出的方法
我得到S_OK,但StringBuilder中的字符串是垃圾
我知道该方法是正确调用的,因为如果我传递了错误的索引,我会得到S_FALSE(正如方法体所定义的那样)
有谁能帮助为Delphi out PChar提供正确的编组吗?尝试使用forName
参数,然后使用获取字符串的内容
参考资料:
那是一个设计相当糟糕的界面。这是一个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#
当然,这假设您可以修改接口。很可能你不能。在这种情况下,您只能使用
out IntPtr
尝试使用IntPtr,然后Marshal.PtrToStringAnsi。“int-get_-FilterName(int-Index,out-IntPtr-Name);”是互操作,PtrToStringAnsi给出了我所希望的:)请将其作为答案写下来。感谢提供详细信息!正如你所说,我不能修改界面,因为它是我在direct show中使用的过滤器的一部分。但是谢谢你的解释。
[PreserveSig]
uint get_FilterName(int Index, out IntPtr Name);
function TDCDSPFilter.get_FilterName(Index: integer;
out Name : WideString): HRESULT; stdcall;
[PreserveSig]
uint get_FilterName(
int Index,
[MarshalAs(UnmanagedType.BStr)]
out string Name
);