【问题标题】:Passing strings in / out of Delphi COM Server将字符串传入/传出 Delphi COM 服务器
【发布时间】:2019-06-26 10:08:16
【问题描述】:

我尝试了以下代码的几种变体,返回 HRESULT(这是更可取的 COM 标准)或返回 BSTR。我也尝试过其他数据类型。我通常会收到“缺少接口方法的实现”编译错误,但是当我使用 WideString 的返回类型时,result:=RetVal; 指令上有一个运行时 AccessViolationException。

我在客户端使用 C#:

var msg = delphi.GetMessage("My Message");

这里是 mi RIDL:

HRESULT _stdcall GetMessage([in] BSTR msg, [out, retval] BSTR* RetVal);

这是我的实现:

function TDelphiCom.GetMessage(msg:WideString; out RetVal:WideString):HRESULT;
var
  tempString: string;
begin
  tempString:=msg;
  RetVal:=WideString(tempString);
end;

将字符串传入/传出 Delphi COM 服务器的正确方法是什么?

【问题讨论】:

  • 这里的代码有什么问题?

标签: delphi com bstr


【解决方案1】:

您的 RIDL 声明是正确的。

您没有显示该方法的 C# 声明,因此我们无法查看您是否正确封送参数。

在 Delphi 方面,您的实现缺少 stdcall 调用约定(以匹配 RIDL 声明)以及异常处理,因此您可以在失败时返回正确的 HRESULT

function TDelphiCom.GetMessage(msg: WideString; out RetVal: WideString): HRESULT; stdcall;
var
  tempString: string;
begin
  try
    tempString := string(msg);
    RetVal := WideString(tempString);
    Result := S_OK;
  except
    // do something...
    Result := DISP_E_EXCEPTION;
  end;
end;

不过,您确实应该改用safecall calling convention 并让它为您处理错误:

function TDelphiCom.GetMessage(msg: WideString): WideString; safecall;
var
  tempString: string;
begin
  tempString := string(msg);
  Result := WideString(tempString);
end;

【讨论】:

  • C# 客户端代码接近问题的顶部 - 仅一行。
  • @KevinS.Miller 在 C# 方面,我指的是方法的 declaration,而不是它的 invokation。我们看不到您如何声明它以知道它是否正确地编组参数。
  • 我们不知道 stdcall 是否丢失,因为没有显示声明,只有实现。用户提供部分代码时总是会出现问题。
  • 也许我不明白关于 C# 声明的问题。 Delphi 代码生成一个 COM 服务器,C# 实例化 COM 服务器对象并调用该服务器的 GetMessage 方法(在 RIDL 中声明,并在 Delphi 中实现)。 RIDL 和 Delphi 都指定 stdcall。
  • 你是对的,上面的Delphi代码没有明确显示stdcall,因为它是在函数原型中声明的,这就是实现。我很遗憾遗漏了。
猜你喜欢
  • 2020-09-11
  • 2014-08-20
  • 1970-01-01
  • 2011-10-08
  • 1970-01-01
  • 2016-06-10
  • 1970-01-01
  • 2013-11-24
  • 2013-01-28
相关资源
最近更新 更多