Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2006.04.16;
Скачать: CL | DM;

Вниз

COM-сервер и procedural var   Найти похожие ветки 

 
tesseract ©   (2006-03-14 17:14) [0]

Имеется такая тема (Com-сервер).

Объявлен родитель у которого имеется  свойство TProcs:array of TCallProc;

TCallProc=procedure (var param:integer) of object;

При загрузке объекта массив соотвественно заполяется процедурами из класса наследника.

И всё ОК - за исключением того, что если попытаться вызвать из присвоенной процедуры какую либо процедуру или получить значение из класса-родителя, то AccessViolation.

Кто нибудь может помочь?


 
clickmaker ©   (2006-03-14 17:56) [1]


> tesseract ©   (14.03.06 17:14)

пример кода с AV?


 
tesseract ©   (2006-03-14 22:19) [2]


> пример кода с AV?

Да длинноват он. И AV я анализирую сам через try/except.

Как я понял при вызове процедуры я теряю поля объекта (как будто он не создан).
Но таблица методов остаётся нетронутой. Это и вызывает AV - как если бы я вызывал методы несозданного объекта.

Весело - методы теоретически должны входить в "рабочее пространство " объекта ибо там и объявлены.


 
clickmaker ©   (2006-03-15 09:49) [3]


> при вызове процедуры я теряю поля объекта

так просто такого не бывает. значит где-то есть кривизна. Может объект и правда где-то случайно убивается


 
tesseract ©   (2006-03-15 10:03) [4]


> так просто такого не бывает. значит где-то есть кривизна.
>  Может объект и правда где-то случайно убивается


Вот в том-то и прикол. После того, как функция возвращает результат. То объект работает как ни в чём не бывало!

Возможно (я в Com я не очень силён), проблема в том что поля находяться в адресном простанстве клиента, а моя функция выполянется в пространстве сервера.  Тогда возникает следующий вопрос - как эту функцию выполнить в контексте клиента?

AV вообще возникает весело - можно посмотреть как поля в памяти располагаются. Смещение AV всегда одно :-)


 
clickmaker ©   (2006-03-15 10:07) [5]


> tesseract ©   (15.03.06 10:03) [4]

нужен все-таки пример кода.. По минимуму, только то, что относится к этим TCallProc


 
tesseract ©   (2006-03-15 10:18) [6]

Ну лови. В принципе присвоение:
описание структур

type TCallFunc=procedure( var paParams:Tparams; var retVal: OleVariant) of object;
type PCallProc= ^tCallProc;


// Пошли методы для добавления/ удаления методов

function TCustomAddIn.MethodAdd(nameeng, namerus: WideString;
 ParamCount: integer; DefVals:Tparams;
   CallProc:PCallProc;CallFunc:PcallFunc): boolean;
var CurDef:integer; // Для установки параметров по умолчанию
begin

{$IFDEF WITH_ADV_CHECKS}
ErrorLog("Adding "+namerus, logNone);

if (nameeng="") or (namerus="") then
 begin
 result:=false;
 exit;
end;
if (not Assigned(CallProc)) and (not Assigned(CallFunc)) then
begin
 result:=false;
 exit;
end;
{$ENDIF}
try
fprocs[ProcCount].name[0]:=nameeng;
fprocs[ProcCount].name[1]:=namerus;
fProcs[ProcCount].ParamCount:=ParamCount;
if DefVals<>nil then
 fprocs[ProcCount].NoDefParam:=false
else
 fprocs[ProcCount].NoDefParam:=true;

@fprocs[ProcCount].CallProc:=CallProc;
@fProcs[procCount].CallFunc:=CallFunc;
if not fprocs[ProcCount].NoDefParam then
 begin
   SetLength(fprocs[ProcCount].DefParams,length(DefVals));
   for CurDef:=0 to Length(DefVals)-1 do
    begin
      fprocs[ProcCount].DefParams[CurDef]:=DefVals[CurDef];
    end;
 end
 else
 fprocs[procCount].DefParams:=nil;
except
on E:Exception do  MessageBox(0, PChar(E.message) , "Error", MB_ICONSTOP or MB_OK);
end;
Inc(ProcCount);
result:=true;

end;

Вызов функции - метод один в один:

// Если функция присвоена то выполняем
if assigned(fprocs[lMethodNum].CallFunc) then
 begin
// Пробуем выполнить
   try
    Pars:=SafeArrayToParams(paParams,fProcs[lMethodNum].ParamCount);
    fProcs[lMethodNum].CallFunc(Pars,pVarRetValue);
   except
    on E:Exception do  MessageBox(0, PChar(E.message) , "Error", MB_ICONSTOP or MB_OK);
   end;
    result:=S_OK;
 end
else
  result := E_FAIL;
ErrorLog("Функция "+inttostr(lMethodNum)+" выполнена",logoRdinary);

Вызов AddMethod

TempFunc:=CallTest;
AddFunction("test","тест",2,@TempFunc);



procedure TCustomObject.CallTest( var paParams:Tparams; var retVal: OleVariant);
var i:integer;
tstr:Widestring;
begin
retval:="";
tstr:="";
// Вот эта функция объявлена в объекте
 ErrorLog("Call test",logOrdinary);
// Если её не вызывать - всё ок иначе - AV. также со всеми полями
 for i:=0 to length(paParams)-1 do
 tstr:=tstr + "параметр" + inttostr(i) +" равен " +  paparams[i] +#13#10;
retval:=tstr;
end;



 
clickmaker ©   (2006-03-15 10:27) [7]

а как ты собcсно вызываешь эту CallTest?
И TCustomObject и TCustomAddIn что за объекты?


 
tesseract ©   (2006-03-15 10:31) [8]

fProcs[lMethodNum].CallFunc(Pars,pVarRetValue); - вот и вызов CallTest.

TcustomAddIn - родитель в котором описаны интерфейсы и логика работы.

TcustomObject - наследник TCustomAddin. Перекрывает функцию инициализации и добавляет процедуры/функции в fproc[].CallProc/CallFunc.

ЗЫ: объекте >1500 строк.


 
clickmaker ©   (2006-03-15 10:35) [9]


> tesseract ©   (15.03.06 10:31) [8]
> fProcs[lMethodNum].CallFunc(Pars,pVarRetValue); - вот и
> вызов CallTest

это изнутри. А с клиента как это выглядит? От создания объекта до вызова


 
tesseract ©   (2006-03-15 10:44) [10]


> это изнутри. А с клиента как это выглядит? От создания объекта
> до вызова

Вот так и выглядит. Клиент передаёт название процедуры, Я нахожу его в массиве fprocs и вызываю.


 
clickmaker ©   (2006-03-15 11:00) [11]


> tesseract ©   (15.03.06 10:44) [10]

т.е. создается объект типа TcustomObject, потом что-то типа
CO.CallMethod("CallTest")
?


 
tesseract ©   (2006-03-15 11:06) [12]

Да типа того, только + куча вспомогательных функций.  
Для справки - это addin для 1c.


 
clickmaker ©   (2006-03-15 11:30) [13]


> TcustomObject - наследник TCustomAddin. Перекрывает функцию
> инициализации

а как перекрывает? полностью или с вызовом inherited? Что там вообще инициализируется?
и AV только на ErrorLog или на любой функции предка?


 
tesseract ©   (2006-03-15 12:31) [14]

Функция объявлена как абстрактная. inherited там нет.


> и AV только на ErrorLog или на любой функции предка?


Не функции  - при обращении к полям объекта из процедуры типа TCALLProc.


 
clickmaker ©   (2006-03-15 12:54) [15]


> Вызов AddMethod
>
> TempFunc:=CallTest;
> AddFunction("test","тест",2,@TempFunc);

еще вот это место не совсем понятно... Зачем TempFunc?
как вообще заполняется массив функций? В конструкторе TCustomObject?


 
tesseract ©   (2006-03-15 13:31) [16]

Ладно сань, спасибо за помощь. Я разобрался. Надо было передавать ссылку на объект. Self  почему-то не работал.


type TCallFunc=procedure(var obj; var paParams:Tparams; var retVal: OleVariant) of object;


И всё ок. Вызываешь метод объекта TCustomAddIn(obj).ErrorLog и всё :-)

Блин во гемор :-)


> еще вот это место не совсем понятно... Зачем TempFunc?как
> вообще заполняется массив функций? В конструкторе TCustomObject?
>


Массив функций заполняется в абстактной initModule, которая вызывается при инициализации объекта. TempFunc - я не могу передать указатель на функцию просто так, сначала нужно скопировать её адрес в переменную.

При выполнении AddProcedure произойдёт её dereference и всё ок.

Насколько я потрейсил - Create/destroy в TcomObject не вызывается. Их заменяют initialize/release.


 
clickmaker ©   (2006-03-15 14:16) [17]

вон оно как...
вообще странно. ErrorLog то хоть объявлена как virtual?


 
tesseract ©   (2006-03-15 14:28) [18]


> вообще странно. ErrorLog то хоть объявлена как virtual?

А зачем? она преспокойно вызывается и так, только без полей.

В перекрытии она вообще-то и не нуждается. Это обёртка над IErrorLog.


 
clickmaker ©   (2006-03-15 15:31) [19]


> TempFunc - я не могу передать указатель на функцию просто
> так

Да почему же?

насчет всего остального... Тут какая фигня с областями видимости переменных. Не знаю, не видя всего кода, трудно разобраться


 
tesseract ©   (2006-03-15 16:10) [20]

Да почему же?

Проверял :-) У меня много перегруженных функций, для заданий функций :-)
Пишет "Variable required".


> насчет всего остального... Тут какая фигня с областями видимости
> переменных. Не знаю, не видя всего кода, трудно разобраться

Это-то я понял. В отладчике прописано "inaccessable value". А не мусор, находимся то мы где положено, но на нас тоже положено. Возможно вмешивается "защитник" Delphi.
Причём не в COM такой код исполняется на ура.


 
clickmaker ©   (2006-03-15 16:14) [21]


> Проверял :-) У меня много перегруженных функций, для заданий
> функций :-)
> Пишет "Variable required".

а зачем ты определяешь указатель на тип TCallProc?
просто
AddMethod(AProc: TCallProc)


 
tesseract ©   (2006-03-15 16:43) [22]


> AddMethod(AProc: TCallProc)

Хм. Щас попробую, но помоему не срабатывало.

Тут ещё прикол. прописал переменную cont:TCustomObject вне определения класса. И знаешь - срабатывает:-)
Осталось выяснить что с ней делать. тк вылезает Oout of memory...


 
tesseract ©   (2006-03-15 16:54) [23]

Так cont начал работь и работать хорошо. Осталось выяснить будет ли на него обнуляться счётчик ссылок?


 
tesseract ©   (2006-03-15 17:13) [24]

Все Сань спасибо . Выяснилось, что как-раз таки из-за ссылок и пахалало.
А зачем использовал? Что-бы nil можно было передавать :-) и меньше функций переписывать :-)



Страницы: 1 вся ветка

Текущий архив: 2006.04.16;
Скачать: CL | DM;

Наверх




Память: 0.53 MB
Время: 0.03 c
10-1116485364
garra
2005-05-19 10:49
2006.04.16
Com-клиент под Delphi 7


15-1143189547
Alarm
2006-03-24 11:39
2006.04.16
Ограничение на количество подключений


4-1137151923
Dimon777
2006-01-13 14:32
2006.04.16
Переключение принтера в режим двусторонней печати


2-1143617570
Лёха
2006-03-29 11:32
2006.04.16
сетевое подключение


2-1142484602
de_ICER-T44
2006-03-16 07:50
2006.04.16
требуется помощь dbf excel