多年前我写了一些COM DLL的i Delphi 4(客户端/服务器)。我没有遇到任何问题。后来我升级到Delphi 7(企业版),现在我遇到了问题:
File-> New -> Other -> ActiveX -> Automation Object --> No problems.
Enter text "TESTPROJ" (CoClass neme) --> No problems.
// Multiple Instances - Multiple Instances
// Threading Model: _ tmAppartment
// Clickbox: Generate support Code -- Unclicked
当我单击OK时,类型库编辑器出现两个LINES i视图部分(ITESTPROJ和TESTPROJ)。这似乎是正确的。
I then click/ mark ITESTPROC. ITESTPROC gets marked. Then I click NEW METHOD.
A new Item (below ITESTPROC - named Method1) appears.
Namebox says METHOD1. ID-box says 201.
但是:
调用Kind-和TYPE-框是灰色的(“禁用”)..
我可以在Invoke kind编辑框中读取“Function”。
问题是:我不能创建任何函数 - 只有这个编辑器的程序。
(我被告知(教导/阅读)我通过设置Invoke类和RETURN类型(在参数中)来创建一个函数,但我根本不能使用Invoke类。
有人可以告诉我为什么吗?如何使用该编辑器创建函数(拼命地需要TLB文件)......
(我已经尝试将返回类型设置为HRESULT,字符串,整数等。这给了我绝对没有 - 只有程序和程序......(带/不带参数)..
答案 0 :(得分:2)
通过IDispatch
接口访问Automation对象中的方法和属性,特别是通过其Invoke()
方法。您定义的任何方法都被强制为“函数”的“调用种类”,因为在调用DISPATCH_METHOD
时将使用Invoke()
标志调用它。这是无法改变的,这就是为什么这个领域是灰色的。默认情况下,“参数”页面上的“返回类型”设置为HRESULT
,保持这种,请参阅下面的原因。
要定义一个返回值的“函数”,您只需创建一个具有参数的方法,该方法使用指针数据类型并标记为Out
和{{1修饰符标志。例如,要创建返回String的函数,请创建一个带有RetVal
[out,retval]
参数的方法。编辑器将生成如下所示的存根实现:
BSTR*
您所要做的就是返回所需的字符串值,例如:
type
TTestProj = class(TAutoObject, IConnectionPointContainer, ITestProj)
...
protected
function Method1: WideString; safecall;
...
end;
function TTestProj.Method1: WideString;
begin
end;
function TTestProj.Method1: WideString;
begin
Result := 'my value';
end;
调用约定将为您处理剩下的事情。要报告错误,只需引发异常即可。 RTL将调用SetErrorInfo()
并向调用者返回适当的safecall
:
HRESULT
如果您没有提出异常,则来电者会收到function TTestProj.Method1: WideString;
begin
if some condition then
raise Exception.Create('error message');
Result := 'my value';
end;
HRESULT
。
您会在实现代码中将该方法视为普通函数,但 CALLER 看到的实际签名是S_OK
。这就是为什么你必须将方法的返回类型设置为function Method1(out Result: WideString): HRESULT; stdcall;
。 Delphi的HRESULT
调用约定在实现方面重新排序,以便于使用。
如果您没有定义具有safecall
标志的任何参数,编辑器将创建“过程”而不是“函数”。例如,如果您创建RetVal
BSTR *参数,则存根实现将如下所示:
[out]
来电者看到的签名是type
TTestProj = class(TAutoObject, IConnectionPointContainer, ITestProj)
...
protected
procedure Method1(out Param1: WideString); safecall;
...
end;
procedure TTestProj.Method1(out Param1: WideString);
begin
end;
。
或者,如果你只是简单地省略参数,那么存根就会像这样结束:
function Method1(out Param1: WideString): HRESULT; stdcall;
来电者看到的签名是type
TTestProj = class(TAutoObject, IConnectionPointContainer, ITestProj)
...
protected
procedure Method1; safecall;
...
end;
procedure TTestProj.Method1;
begin
end;
。