Dynamiczne tworzenie parametrów i typów funkcji

0

Witam,
moje pytanie dotyczy funkcji, które mam zapisane w formie wskaźnika. Otóż deklaruje funkcje na zasadzie dynamicznego ładowania z biblioteki:

var
  P: Pointer;
begin
{...}
P := GetProcAddress(handle, 'MessageBoxA');

Następnie w celu wywołania takiej funkcji utworzyć musze odpowiedni typ, który będzie pasował do danej funkcji w celu jej wywołania, czyli:

type
  t0 = function(hWnd: HWND; lpText, lpCaption: PChar; uType: UINT): Integer; stdcall;
{...}

t0(P)(Handle, 'Tekst', 'Caption', 0);

Moje pytanie brzmi, w jaki sposób utworzyć dynamicznie taki typ jakiego bym wymagał albo w jaki sposób przekazać każdy z parametrów do funkcji? Chodzi mi o to, że mam wiele funkcji wraz z opisem poszczególnych parametrów i nie wchodzi u mnie w gre utworzenie tysiaca linijek tekstu z roznymi typami i ich kombinacjami (raz funkcja która ma jako dwa parametry dwa PChar, raz jeden, raz Integer itd). Jak cos takiego tworzyc dynamicznie? Dziekuje z gory za pomoc

dodanie znaczników <code class="delphi"> - fp

2

Widzę przynajmniej dwa rozwiązania:
1.cdecl + Array of Const (powinno zadziałać we FPC, natomiast nie wiem jak w Delphi).
2.Dyrektywa varargs (http://www.freepascal.org/docs-html/ref/refsu80.html):

Type TProc = Procedure varargs;
{...}
TProc(P)(10, 20, @P, 'hello world!', some_var);

Btw, FPC zdaje się mieć problem z deklarowaniem `procedure-variable` wraz z `varargs`, będę musiał sprawdzić, czy naprawili w 2.7.0 :P Edit: nope, FPC 2.7.0 również tego nie ma, pora przyszykować bugreport ;p
0

Dokładnie jak napisal @Patryk27 cdecl i varargs powinny zadziałać i pod Delphi. Ja pod Delphi 7 od dawna w programach WinAPI korzystam z takiego kodu jak poniżej. Wygooglowałem go kiedyś i się go trzymam. Widać tutaj nietypowy zapis najpierw definicja funkcji, później deklaracja po słowie kluczowym var. Można tego uniknąć jeśli robimy zbiorczy moduł z deklaracjami i definicjami własnych rzeczy. Wtedy ponoć niezalecane słowo kluczowe forward zapisane na koncu takiego kodu jak po var poniżej - jest chyba jedynym "wybawieniem". Oczywiście link, ktory podał @Patryk27, również sporo wyjaśnia, jak można to zrobić jeszcze inaczej. Dodam, że sam się na tym przyłapałem iż to, w jaki sposób nazwałem tę funkcję może nawiązywać do systemowego polecenia format c: ;) Jednak miałem tutaj na myśli właśnie konwencje wywołania z języków C/C++, gdzie mamy po printf możliwosć zmiennej ilości parametrów dla formatowanego stringa, a nie jak jest to pod Delphi z funkcją Format z modułu SysUtils, gdzie parametry podajemy jako zbiór. Chociaż wątpie i tak, czy ktoś potrzebował by podawać ich więcej niż 255.

function _FormatC(const Format : string) : string; cdecl;
const
  StackSlotSize = SizeOf(Pointer);
var
  Args : VA_List;
  Buffer : array[0..1024] of Char;
begin
  Args := VA_List(PAnsiChar(@Format) + ((SizeOf(Format) + StackSlotSize - 1) and not (StackSlotSize - 1)));
  SetString(Result, Buffer, wvsprintfA(Buffer, PChar(Format), Args));
end;

var
  FormatC : function(const Format : string) : string; cdecl varargs = _FormatC;
0

@Patryk27, @olesio: zapominacie, że taki MessageBoxA jest stdcall a nie cdecl...

Chodzi mi o to, że mam wiele funkcji wraz z opisem poszczególnych parametrów i nie wchodzi u mnie w gre utworzenie tysiaca linijek tekstu z roznymi typami i ich kombinacjami (raz funkcja która ma jako dwa parametry dwa PChar, raz jeden, raz Integer itd)
Nie chcę cię zmartwić, ale tak to się zwykle właśnie robi. Spójrz choćby na źródła unitu Windows.

0

Cóż, FPC nie pozwala na korzystanie z varargs, jeżeli jest inna konwencja. Nie wiem, jak Delphi.

0

@Azarien: zgadza się. Akurat funkcje z modułu Windowsstdcall. I tutaj pozostaje kombinowanie niestety tak, jak są zbudowane moduły obsługujące WinAPI w Delphi. Z tym, że ja zrozumiałem iż pytający chce operować na przez siebie stworzonej dllce albo ma dllkę, w której konwencja wywołań to cdecl. No coż - pomyliłem się.

0

Zawsze można skorzystać z typów generycznych: http://ideone.com/vmWNJO ;)

0
Patryk27 napisał(a):

Cóż, FPC nie pozwala na korzystanie z varargs, jeżeli jest inna konwencja. Nie wiem, jak Delphi.

Nie wszystkie konwencje umożliwiają zmienną ilość parametrów. stdcall jest tak zbudowane, że zastosowanie varargs jest niemożliwe.

To dotyczy 32-bitów pod Windows, bo pod x64 nie ma różnicy między stdcall a cdecl; zamiarem Microsoftu było stworzenie jedynie słusznej konwencji wywołania, tak by problem różnych konwencji raz na zawsze znikł. Nie dotrzymali jednak słowa, bo Visual 2013 wprowadzi nową konwencję vectorcall ;-)

0
Patryk27 napisał(a):

Cóż, FPC nie pozwala na korzystanie z varargs, jeżeli jest inna konwencja. Nie wiem, jak Delphi.

Dokładnie varargs nie, ale ma na to swoje sposoby takie jak array of const

0

Dziekuje za pomoc ; ))

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