首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >当Delphi类型为"out PChar“时,我使用什么PChar参数类型?

当Delphi类型为"out PChar“时,我使用什么PChar参数类型?
EN

Stack Overflow用户
提问于 2014-02-09 23:57:13
回答 2查看 998关注 0票数 1

我无法将下面的界面定义从Delphi转换为C#:

代码语言:javascript
复制
  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的方式如下:

代码语言:javascript
复制
[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,这两种方法都失败了,其中有一条错误消息,表示不允许这种编组组合。

德里采用这种方法的定义是:

代码语言:javascript
复制
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声明为:

代码语言:javascript
复制
property Name[Index: integer]: String read GetName;

我的所有其他接口方法都能很好地与其他基本类型(in和ref)一起工作,除了这个具有PChar输出的接口。

我得到了S_OK,但是StringBuilder中的字符串是垃圾.

我知道方法是正确调用的,因为如果我传递了错误的索引,我就会得到S_FALSE (就像方法体定义的那样)。

有人能帮忙为Delphi提供适当的编组吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-02-10 00:57:05

尝试将IntPtr用于Name参数,然后使用Marshal.PtrToStringAnsi获取字符串的内容。

参考资料:

“在C#中

到C#中的字符串

票数 1
EN

Stack Overflow用户

发布于 2014-02-10 07:28:48

这是一个设计得相当糟糕的接口。这是一个COM接口,所以它应该使用COM字符串BSTR

但是,C#端必须将PChar作为IntPtr类型的out参数进行封送。宣言应包括:

代码语言:javascript
复制
[PreserveSig]
uint get_FilterName(int Index, out IntPtr Name);

然后,可以通过调用Marshal.PtrToStringAnsiMarshal.PtrToStringUni来恢复字符串,具体取决于字符串的编码。

您不能使用StringBuilder,因为这适用于调用方分配缓冲区的情况。而这不是在这里发生的。

正如我所说,使用COM字符串会更好。代码如下所示:

Delphi

代码语言:javascript
复制
function TDCDSPFilter.get_FilterName(Index: integer; 
    out Name : WideString): HRESULT; stdcall;

C#

代码语言:javascript
复制
[PreserveSig]
uint get_FilterName(
    int Index,
    [MarshalAs(UnmanagedType.BStr)]
    out string Name
);

当然,这假设您可以修改接口。很可能你做不到。在这种情况下,您将使用out IntPtr

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21666846

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档