Method pointer i regular procedure

0

Mam ciężki orzech do zgryzienia...

Przykład:

type
TProcka = procedure(Param: Pointer); stdcall;

TKlasa = class(TObject)
  procedure ProckaTworzaca;
  procedure ProckaWywolywana(Param: Pointer);
end;

procedure JakiesWywolanie(Procka: TProcka); stdcall; external 'jakis.dll';

procedure TKlasa.ProckaTworzaca;
begin
  JakiesWywolanie(@ProckaWywolywana);
end;

procedure TKlasa.ProckaWywolywana(Param: Pointer);
begin
  // tutaj coś tam
end;

Produkuje to błąd:
[Error] Incompatible types: 'regular procedure and method pointer'

Nie przechodzi, ponieważ typ TProcka nie jest "of object" i jak się zrobi w poniższy sposób to działa:

type
TProcka = procedure(Param: Pointer); stdcall;

TKlasa = class(TObject)
  procedure ProckaTworzaca;
end;

procedure JakiesWywolanie(Procka: TProcka); stdcall; external 'jakis.dll';

procedure TKlasa.ProckaTworzaca;
begin
  JakiesWywolanie(@ProckaWywolywana);
end;

procedure ProckaWywolywana(Param: Pointer);
begin
  // tutaj coś tam
end;

Po wyjęciu "ProckaWywolywana" z klasy wszystko jest ok, jednakże planuję utworzyć kilka obiektów tej klasy, z których każda, możliwe nawet, że równolegle, będzie korzystać z "ProckaWywolywana", z poziomu której potrzebuję mieć dostęp do danych obiektu, który utworzył wywołanie. Robiąc to według przykładu pierwszego jest wszystko ok, ale kompilator tego nie przepuszcza. W drugiej wersji musiałbym tworzyć jakąś tablicę obiektów, przesyłać dodatkowy parametr, a potem porównywać i wywoływać "kopię" procedury metodą w odpowiednim obiekcie.

TKlasa = class(TObject)
  procedure ProckaTworzaca;
  procedure KopiaProcki(Param: Pointer);
end;

procedure ProckaWywolywana(Param: Pointer);
begin
  // tutaj muszę "odgnadnąć" z jakiego obiektu przyszło wywołanie
  OdpowiedniObiekt.KopiaProcki(Param);
end;

A jest dość uciążliwe. Zna ktoś jakiś sposób na to? Chcę przekazać adres metody, a nie procedury, a w zasadzie metoda to tak czy siak procedura chyba, co nie?

0

No a dlaczego nie zrobisz tej deklaracji jako metody ?

TProcka = procedure(Param: Pointer) of object; stdcall;

Jedyne o czym musisz pamiętać to to że do metody jest jeszcze niejawnie przekazywany wskaźnik self. Czyli jeśli deklarujesz funkcje dla dll i jest to funkcja/procedura która nie należy do klasy (czyli nie jest metodą) to musisz ją zadeklarować tak:

  TProcka = procedure(Param: Pointer, Obiekt: Pointer); stdcall; //niestety nie wiem czy self jest jako   pierwszy czy jako ostatni , musisz to sam sprawdzić
  JakasProcedurka(Procka : TProcka);
  begin
  ...
  end;
0
Osiołek napisał(a)

Chcę przekazać adres metody, a nie procedury, a w zasadzie metoda to tak czy siak procedura chyba, co nie?
No wlasnie nie;) Roznica miedzy metoda a procedura jest taka, ze dla metody zwracana jest para wskaźników. Jeden wskaźnik na wołana metode a drugi na obiekt, który tą metode wołał.

Delphi + F1 + procedural types. Poradzisz sobie na pewno, powodzenia!

0

Jesli wszystko jest w delphi (lacznie z tym eksportem - tego nie podales) to mozesz zamienic definicje na

TProcka = procedure(Param: Pointer)  of object;

Jednak jesli mieszasz to np z WinAPI czy bibliotekami, ktore potrzebuja dokladnie takiej definicji to wtedy poprzednio podane metody.

0

Właśnie sęk w tym, że mam to w nie mojej bibliotece i nie mogę tego zmodyfikować. Dodatkowo dochodzi fakt, że wiążę to z wątkami i trochę nagmatwałem :D. Funkcja zwrotna ma możliwość przekazania user-variable typu DWord i wsadziłem w to Integer(Self), a potem TKlasa(User) i jako tako jest git. Dzięki za naprowadzenie, zupełnie nie pomyślałem o przekazaniu wskaźnika na obiekt, a to takie proste :-D .

0
reichel napisał(a)

Jesli wszystko jest w delphi (lacznie z tym eksportem - tego nie podales) to mozesz zamienic definicje na

TProcka = procedure(Param: Pointer)  of object;

Jednak jesli mieszasz to np z WinAPI czy bibliotekami, ktore potrzebuja dokladnie takiej definicji to wtedy poprzednio podane metody.

Dzieki wielkie!!!!!! :)
To rozwiazalo takze moj problem :)

1 użytkowników online, w tym zalogowanych: 0, gości: 1