COM高手看过来!(300分)(300分)

  • 主题发起人 主题发起人 我是左派
  • 开始时间 开始时间

我是左派

Unregistered / Unconfirmed
GUEST, unregistred user!
我现在要做一个非常简单的COM控件。要完成的功能如下:
在服务器放定义一个函数,有输入,有输出。形式如下:
function getstring(param1:integer):string;
意思就是想用这个函数对输入的整数作一些处理,然后再以字符串的形式返回输出的结果。
就这么的功能,很简单的。
于是我作如下操作:
先建立一个COM对象,命名为SRV,接口为ITEST和TEST。
在ITEST下我建一个METHOD,命名为GetString,然后再在Parameters页加一个参数:Value.
TYPE为BSTR* ,Modifier为[out,retval].添加完毕后再添加一个参数Param1,type为long,
Modifier为[in].
然后REFRESH,就会在TestIMPL.pas文件中看到函数GetString 的定义如下:
type
TTest = class(TObject, ITest)
protected
function getName(Param1: Integer): WideString; safecall;
{ Protected declarations }
end;
我在下面的实现部分添加代码:
function TTest.SetName(Param1: Integer): WideString;
begin
result:=intTOstr(param1);
end;
运行、注册都正常。
然后再做一个客户端。在Form1的private部分定义一个接口变量F:ITest.

if F=nil then
F:=ITestObject(CoTestObject.Create);
i:=22;
//到下面出错。
edit1.text:=f.SetName(i);
出错的代码是:Types of actual and formal var parameters must be indentical

上面的程序是我看完《DELPHI4编程技术内幕》之后的例子。原书的例子是返回一个时间。
我试过,很正常。

我不知道我的这个代码错在那里。现在帖出来望大家能够讨论讨论。
 
var
F:ITestObject;
begin
F:=CoTestObject.Create;

edit1.text:=f.SetName(i);

.
.
end;
 
首先我觉得result:=intTOstr(param1);并没有返回一个WideString类型
string和WideString是有差别的
其次edit1.text:=f.SetName(i);
f.SetName(i)应该转化为String类型,类型才匹配

 
首先,这并不属于COM的错误,而是DELPHI发现你传入的参数类型与函数声明的类型不符
我觉得应该是那个参数I的问题
或者你可以试一试
定义一个S: WideString
S := F.SetName(I)
如果还是出错,那说明是I的问题了,因为你没写I是怎么定义的,所以我也没法判断。
 
刚才看到一个很奇怪的事情:我输入F后再敲一个".",DELPHI提示setname里面的
变量类型是"widestring"类型!即:
function getname(var param1:widestring):widestring;
我还以为我自己把SERVER端的输入的变量类型改掉了,赶忙打开一看,发现SERVER端的
定义还是原来的样子,我并没有改!
function getname(var param1:integer):widestring;
这是为什么?
widestring是一个什么类型?
我刚才这样做:先定义一个widestring类型的变量s,对其赋值 s:='ss';
然后再调用edit1.text=f.getname(s),正常,可以运行!
但是,我发现EDIT里面的内容是 1242592!并不是所需要的ss!
这又是为什么?
 
呵呵,怎么没有人继续回答呢?
 
你的代码是从你的程序中拷贝的吗? 怎么会有这种错误: TTest = class(TObject, ITest)
我想应该是 TTest = class(TAutoObject, ITest) 吧.
我把我的代码贴上来,我试过了, 没有问题
COM Server:
....
type
TTest = class(TAutoObject, ITest)
protected
function getName(value: Integer): WideString; safecall;
end;

implementation

uses ComServ;

function TTest.getName(value: Integer): WideString;
begin
Result:=IntToStr(value);
end;

initialization
TAutoObjectFactory.Create(ComServer, TTest, Class_Test,
ciMultiInstance, tmApartment);
end.

Client:
procedure TForm1.Button1Click(Sender: TObject);
var
_I : ITest;
i : Integer;
begin
i:=44;
_I:=CoTest.Create;
Edit1.Text:=_I.getName(i);
_I:=nil;
end;
 
我测试了一个,没有问题;
首先新建一ACTIVEX LIBRARY,然后建一COM OBJECT;
COCLASS NAME为RESULTSTR,它IMPLEMENTED INTERFACE为IRESULTSTR,你不要更改它;
按缺省值就行了,然后增加一方法resultsr,RESULT TYPE为BSTR;增加一参数INPUTVALUE为INT型;
刷新,然后在TLB中该方法处写代码:RESULT:=INTOSTR(INPUTVALUE);注册;

这里比较重要:
客户端,首先导入TYPE LIBRARY,在PROJECT的IMPORT TYPE LIBRARY处,加入当前COM对象
的DLL文件,然后单击CREATE UNIT,在主窗体中引入该单元;
在主窗体中:
procedrue tform1.button1click(sender:tobject);
var
va:iresultstr;
begin
va:=coresultstr.create;
button1.caption:=va.resultsr;
end;
D6I测试通过。
 
to 我是左派:
在COM接口传递的字符串全是UNICODE字符串,所以在DELPHI声明是WideString!
  另外,连你自己也没搞懂你自己在做什么,一会是
function getName(Param1: Integer): WideString; safecall;
  一会又是
  function getname(var param1:widestring):widestring;
  叫我们怎么帮你看啊?

总之,你如果是以VAR参数方式传入的,类型必须一样才能编译通过的!
 
后退
顶部