Форум: "Основная";
Текущий архив: 2002.04.18;
Скачать: [xml.tar.bz2];
ВнизInterface и указатель Найти похожие ветки
← →
Dimka Maslov (2002-04-04 11:05) [6]если ты предпочитаешь, чтобы все было под твоим контролем - ты создаёшь объект, ты его и уничтожаю, когда тебе этого захочется, то наследуй объект, реализующий интерфейс не от TInterfacedObject, а от TObject, и твой код должен выглядеть так
IMyInterface=interface
["{2D67E340-4705-11D6-A1F0-444553540000}"]
function Funct:integer;
end;
TMyClass=class(TObject, IMyInterface)
function _AddRef: Integer; stdcall;
function _Release: Integer; stdcall;
function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
function Funct:integer;
end;
function TMyClass._AddRef: Integer;
begin
Result:=-1;
end;
function TMyClass._Release: Integer;
begin
Result:=-1;
end;
function TMyClass.QueryInterface(const IID: TGUID; out Obj): HResult;
begin
if GetInterface(IID, Obj) then Result:=S_OK else Result:=E_NOINTERFACE;
end;
function TMyClass.Funct;
begin
Result:=3;
end;
function TForm1.Button1Click(Sender: TObject);
var
Obj: TMyClass;
Ifc: IMyInterface;
begin
Obj:=TMyClass.Create;
try
Obj.GetInterface(IMyInterface, Ifc);
// Делаешь все что захочешь с Ifc, но всё равно вызывать Ifc._Release не надо
finally
Obj.Free;
end;
end;
А теперь разберёмся понятиями "переменная процедурного типа" "указатель на интерфейс" и просто "указатель".
Как известно, указатель есть переменная содержая адрес ячейки памяти, безотносительно тому, что содержится в этой ячейке.
Переменная процедурного типа - тоже указатель, но указывает он на точку входа в конкретную процедуру.
Указатель на интерфейс - есть указатель на таблицу методов интерфейса, перым членом которой является указатель на метод QueryInterface.
Разберёмся теперь с почему не работает твой первый пример и работает второй...
procedure TForm1.Button1Click(Sender: TObject);
var
cl:TMyClass;
p,p1:pointer;
begin
cl:=TMyClass.Create;
// Создание объекта
cl.GetInterface(IMyInterface, p);
// получение указателя на интерфейс и запись его в нетипизированный указатель.
QI:=p;
// связывание переменной продедурного типа с нетипизированным указателем, указывающим на таблицу методов, первым из которых стоит метод function (Self: IMyInterface; const IID: TGUID; out Obj): HResult stdcall; ты же присваиваешь адрес этой процедуры переменной, которая ссылается на процедуру function (IID: TGUID; out Obj): LongInt register;. Имеющую разные аргументы и разный формат вызова, что неминуемо приведет к ошибке при вызове такой процедуры через указатель...
QI(IMyInterface,p1); //Invalid pointer operation
// что и происходит
cl._Release;
end;
Во втором случае ты связываешь procedure с procedure по этому всё работает.
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2002.04.18;
Скачать: [xml.tar.bz2];
Память: 0.45 MB
Время: 0.007 c