如何从 COM 服务器返回 WideString?

发布于 2024-10-02 02:42:12 字数 1150 浏览 7 评论 0原文

_TLB.pas 文件中的此接口

// *********************************************************************//
// Interface: ITMyCOM
// Flags: (256) OleAutomation
// GUID: {D94769D0-F4AF-41E9-9111-4D8BC2F42D69}
// *********************************************************************//
ITMyCOM = interface(IUnknown)
['{D94769D0-F4AF-41E9-9111-4D8BC2F42D69}']
function MyDrawWS(a: Integer; b: Integer): WideString; stdcall;
end;

这会查看

[
odl,
uuid(D94769D0-F4AF-41E9-9111-4D8BC2F42D69),
version(1.0),
helpstring("Interface for TMyCOM Object"),
oleautomation
]
interface ITMyCOM : IUnknown {
BSTR _stdcall MyDrawWS(
[in] long a, 
[in] long b);
};

COM 服务器中的操作系统 Windows 函数,看起来就像

function TTMyCOM.MyDrawWS(a, b: Integer): WideString;
begin
Result := WideString(IntToStr(a+b));
end;

在 COM 客户端中,我正在调用此函数

Edit1.Text := String(MyCOM.MyDrawWS(1,1));

,并收到错误第一次机会异常,位于 $75A9FBAE。异常类 EAccessViolation,带有消息“模块‘RPCRT4.dll’中地址 75A409A4 处的访问冲突”。读取地址 FFFFFFF8'。 Process Project1.exe (2296)

如果我想返回 Integer,这是可行的。如何返回宽字符串?

This Interface at _TLB.pas file

// *********************************************************************//
// Interface: ITMyCOM
// Flags: (256) OleAutomation
// GUID: {D94769D0-F4AF-41E9-9111-4D8BC2F42D69}
// *********************************************************************//
ITMyCOM = interface(IUnknown)
['{D94769D0-F4AF-41E9-9111-4D8BC2F42D69}']
function MyDrawWS(a: Integer; b: Integer): WideString; stdcall;
end;

This looks at OS Windows

[
odl,
uuid(D94769D0-F4AF-41E9-9111-4D8BC2F42D69),
version(1.0),
helpstring("Interface for TMyCOM Object"),
oleautomation
]
interface ITMyCOM : IUnknown {
BSTR _stdcall MyDrawWS(
[in] long a, 
[in] long b);
};

Function in COM server looks as

function TTMyCOM.MyDrawWS(a, b: Integer): WideString;
begin
Result := WideString(IntToStr(a+b));
end;

In COM Client i`m calling this function like

Edit1.Text := String(MyCOM.MyDrawWS(1,1));

and get error First chance exception at $75A9FBAE. Exception class EAccessViolation with message 'Access violation at address 75A409A4 in module 'RPCRT4.dll'. Read of address FFFFFFF8'. Process Project1.exe (2296)

If i want returning Integer, it`s works. How to return WideString?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

臻嫒无言 2024-10-09 02:42:12

处理这个问题的正确方法如下:

[ 
odl, 
uuid(D94769D0-F4AF-41E9-9111-4D8BC2F42D69), 
version(1.0), 
helpstring("Interface for TMyCOM Object"), 
oleautomation 
] 
interface ITMyCOM : IUnknown { 
HRESULT _stdcall MyDrawWS( 
[in] long a,  
[in] long b,
[out, retval] BSTR* ret); 
}; 

ITMyCOM = interface(IUnknown) 
  ['{D94769D0-F4AF-41E9-9111-4D8BC2F42D69}'] 
  function MyDrawWS(a: Integer; b: Integer; out ret: WideString): HResult; stdcall; 
end; 

function TTMyCOM.MyDrawWS(a, b: Integer; out ret: WideString): HRESULT; 
begin 
  ret := IntToStr(a+b);
  Result := S_OK;
end; 

var
  W: WideString;
begin
  OleCheck(MyCOM.MyDrawWS(1, 1, W));
  Edit1.Text := W;
end;

然后可以通过在接口的 Delphi 声明(而不是 TypeLibrary 本身)中使用 Delphi 的 safecall 调用约定来稍微简化:

ITMyCOM = interface(IUnknown) 
  ['{D94769D0-F4AF-41E9-9111-4D8BC2F42D69}'] 
  function MyDrawWS(a: Integer; b: Integer): WideString; safecall;
end; 

function TTMyCOM.MyDrawWS(a, b: Integer): WideString;
begin 
  Result := IntToStr(a+b);
end; 

Edit1.Text := MyCOM.MyDrawWS(1, 1);

The correct way to handle this is as follows:

[ 
odl, 
uuid(D94769D0-F4AF-41E9-9111-4D8BC2F42D69), 
version(1.0), 
helpstring("Interface for TMyCOM Object"), 
oleautomation 
] 
interface ITMyCOM : IUnknown { 
HRESULT _stdcall MyDrawWS( 
[in] long a,  
[in] long b,
[out, retval] BSTR* ret); 
}; 

ITMyCOM = interface(IUnknown) 
  ['{D94769D0-F4AF-41E9-9111-4D8BC2F42D69}'] 
  function MyDrawWS(a: Integer; b: Integer; out ret: WideString): HResult; stdcall; 
end; 

function TTMyCOM.MyDrawWS(a, b: Integer; out ret: WideString): HRESULT; 
begin 
  ret := IntToStr(a+b);
  Result := S_OK;
end; 

var
  W: WideString;
begin
  OleCheck(MyCOM.MyDrawWS(1, 1, W));
  Edit1.Text := W;
end;

Which can then be simplified a little by using Delphi's safecall calling convention in the Delphi declaration (not in the TypeLibrary itself) of the interface:

ITMyCOM = interface(IUnknown) 
  ['{D94769D0-F4AF-41E9-9111-4D8BC2F42D69}'] 
  function MyDrawWS(a: Integer; b: Integer): WideString; safecall;
end; 

function TTMyCOM.MyDrawWS(a, b: Integer): WideString;
begin 
  Result := IntToStr(a+b);
end; 

Edit1.Text := MyCOM.MyDrawWS(1, 1);
恋竹姑娘 2024-10-09 02:42:12

让 Delphi 自动执行转换。别投。您可以将 (ansi) 字符串转换为 PChar,因为它们的内存布局是兼容的,但您不能将字符串转换为宽字符串,反之亦然。当您将一个分配给另一个时,Delphi 将执行转换。

在德尔福< 2009年

var
S: string;
W: WideString;
...
S := W;  // Conversion, WideString -> AnsiString;
W := S; // Conversion, AnsiString -> WideString

Let Delphi perform the conversions automatically. Don't cast. You can cast a (ansi)string to a PChar, because their memory layout are compatible, but you can't cast a string to a widestring or viceversa. Delphi will perfrom conversion when you assign one to the other.

In Delphi < 2009

var
S: string;
W: WideString;
...
S := W;  // Conversion, WideString -> AnsiString;
W := S; // Conversion, AnsiString -> WideString
愚人国度 2024-10-09 02:42:12

不要使用 HRESULT 以外的返回值。而是将您的返回值作为输出参数放入参数列表中。

function MyDrawWS(a: Integer; b: Integer; out str : WideString): HRESULT; stdcall;

这样,你也被迫使用COM内存管理器IMalloc(CoTaskMemAlloc用于pur COM,SysAllocString用于Automation)。

Don't use return values other than HRESULT. Instead put your return value into parameter list as output parameter.

function MyDrawWS(a: Integer; b: Integer; out str : WideString): HRESULT; stdcall;

In this way, you are also forced to use COM memory manager IMalloc (CoTaskMemAlloc for pur COM, SysAllocString for Automation).

软糖 2024-10-09 02:42:12

您需要使用 SysAllocString()SysAllocStringLen() 分配 BSTR。

You need to use SysAllocString() or SysAllocStringLen() to allocate the BSTR.

深空失忆 2024-10-09 02:42:12

第一次机会例外,价格为 75A9FBAE。异常类 EAccessViolation,带有消息“模块‘RPCRT4.dll’中地址 75A409A4 处的访问冲突

  1. 错误来自 RPCRT4.dll

  2. EAccessViolation 主要是由访问引起的如果是 null 对象,请单步执行您的代码,确保所有对象都是有效对象。

First chance exception at $75A9FBAE. Exception class EAccessViolation with message 'Access violation at address 75A409A4 in module 'RPCRT4.dll'

  1. the error is coming from RPCRT4.dll

  2. EAccessViolation is mostly caused by accessing a null object, step through your code make sure all objects are valid objects.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文