此接口位于_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;
这是关于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);
};
COM服务器中的功能看起来像
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'。处理Project1.exe(2296)
如果我想要返回Integer,那就行了。如何返回WideString?
答案 0 :(得分:1)
请勿使用HRESULT以外的返回值。而是将返回值作为输出参数放入参数列表中。
function MyDrawWS(a: Integer; b: Integer; out str : WideString): HRESULT; stdcall;
通过这种方式,您还被迫使用COM内存管理器IMalloc(CoTaskMemAlloc用于pur COM,SysAllocString用于自动化)。
答案 1 :(得分:1)
让Delphi自动执行转换。不要施放。您可以将(ansi)字符串转换为PChar,因为它们的内存布局是兼容的,但您不能将字符串转换为宽字符串或反之亦然。当您将一个指定给另一个时,Delphi将进行转换。
在德尔福< 2009年
var
S: string;
W: WideString;
...
S := W; // Conversion, WideString -> AnsiString;
W := S; // Conversion, AnsiString -> WideString
答案 2 :(得分:1)
处理此问题的正确方法如下:
[
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);
答案 3 :(得分:0)
您需要使用SysAllocString()
或SysAllocStringLen()
来分配BSTR。
答案 4 :(得分:0)
$ 75A9FBAE的第一次机会异常。异常类EAccessViolation,消息'模块'RPCRT4.dll'中地址为75A409A4的访问冲突
错误来自RPCRT4.dll
EAccessViolation主要是通过访问空对象引起的,单步执行代码确保所有对象都是有效对象。