![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Ошибка вызова процедуры COM-сервера [D6, Win2k]
DmitryMN © (2002-09-05 13:38:00)2. Почему если я вызываю сервер через Variant, и результат функции присваиваю
какой-нибудь переменной, происходит ошибка Invalid Callee:
var
V:Variant;
d:double;
begin
V:=CreateOleObject("MemoSrv.MemoIntf");
d:=V.GetNumber;
end;
Однако при вызове процедуры такого не происходит.
Сервер внешний, поддерживает IDispatch.
DmitryMN (2002-09-06 11:48:00) [1]To Набережных С.:
Кстати в заголовке функции GetNumber должно быть так
function GetNumber( Value: double): HResult; stdcall;
или так
function GetNumber( out Value: double): HResult; stdcall;
DmitryMN (2002-09-06 11:22:00) [2]Спасибо - все заработало:)
Набережных С. (2002-09-05 19:40:00) [3]
> function GetNumber(out Result double): HResult; stdcall;
:))))
Только сейчас обратил внимание, надо было так подправить:
function GetNumber( Value: double): HResult; stdcall;
Набережных С. (2002-09-05 19:14:00) [4]Даже не знаю, с чего начать :) SafeCall - чисто дельфийская обертка-декларация. Она заставляет компилятор сгенерить в сервере нечто вроде этого(в первом приближении):
function GetNumber(out Result double): HResult; stdcall;
begin
try
//твой код
Result:=0;
except
on E:EOleException do Result:=E.ErrorCode;
else Result:=E_UNEXPECTED;
end;
end;
хотя в исходном коде у тебя он описан так:
function GetNumber: Double;
begin
//твой код
end;
А описание в IDL - это то, как метод описан в библиотеке типов, т.е. как он РЕАЛЬНО реализован в исполняемом коде.
Соглашение-же о безопасном вызове требует, что-бы любой метод в Automation возвращал hresult. И хотя это не жестко обязательно, однако VB, например, может работать только с такими методами.
Ну а SafeCall - это для нашего всеобщего удобства только :).
Digitman (2002-09-05 18:52:00) [5]А как тогда понять несоответствие
IDL: id(0x00000002)
TLB: dispid 5;
???
DmitryMN (2002-09-05 18:29:00) [6]Так ведь safecall и обеспечивает то что функция записанная как
function GetNumber: Double; safecall;
будет воспринята как
function GetNumber(out Result double): HResult; stdcall;
Она ведь работает при вызове сервера из интерфейса, а при вызове из variant - нет
Набережных С. (2002-09-05 18:23:00) [7]
> DmitryMN (05.09.02 16:51)
Не, брат, что-то не похоже на SafeCall. В IDL он должен выглядеть примерно так:
[
id(0x00000002)
]
hresult _stdcall GetNamber([out, retval] double * Value );
Что-то ты где-то напортачил. Попробуй удалить и заново объявить его в библиотеке типов. Только удали его и в классе.
DmitryMN (2002-09-05 18:14:00) [8]IMemoIntfDisp = dispinterface
["{0D7215D9-1DBC-4571-AE89-159984AD85B0}"]
function GetNumber: Double; dispid 5;
end;
Digitman (2002-09-05 17:55:00) [9]приведи соответствующее объявление в MemoSrv_TLB.pas
IMemoIntfDisp = dispinterface
... ???
end;
DmitryMN (2002-09-05 16:51:00) [10]Методобъявлен как safecall
Объявление метода в TMemoIntf:
function TMemoIntf.GetNumber: Double;
begin
Result:=FNumber;
end;
и в IDL:
[
id(0x00000002)
]
double _stdcall GetNumber( void );
Digitman (2002-09-05 16:12:00) [11]Метод объявлен как safecall ?
Набережных С. (2002-09-05 15:56:00) [12]Покажи объявление метода в TMemoIntf и, желательно, в IDL.
DmitryMN (2002-09-05 14:20:00) [13]V:=CreateOleObject("MemoSrv.MemoIntf") - сервер создается - он появляется на экране и можно выполнить любую его процедуру, однако - когда дело доходит до функций - тут и возникает эта ошибка
d:=V.GetNumber - да - метод объявлен в интерфейсе MemoIntf.
Объект поддерживает этот интерфейс:
TMemoIntf = class(TAutoObject, IMemoIntf),
и сам метод GetNumber реализован в этом объекте.
Digitman (2002-09-05 14:12:00) [14]V:=CreateOleObject("MemoSrv.MemoIntf"); // ты уверен, что V not is Null после выполнения этой строчки ?
d:=V.GetNumber; // ты уверен, что объект поддерживает данный метод ?
DmitryMN (2002-09-05 14:06:00) [15]Побовал - тот же эффект
Eduard (2002-09-05 13:55:00) [16]По всей видимости, переменная d должна иметь тип OleVariant