Delphi "Array von Const" zu "Varargs"

8

Bitte helfen Sie! Ich brauche diese Konvertierung, um Wrapper für einige C-Header für Delphi zu schreiben.

Als ein Beispiel:

%Vor%

Wie kann ich "array of const" in "varargs" umwandeln?

bearbeiten : Funktion PushString befindet sich tatsächlich im Datensatz (ich habe ein vereinfachtes Beispiel angegeben), und ich habe keinen direkten Zugriff auf den Pushstring. Direkter Anruf ist ausgeschlossen.

edit 2 : Ich schreibe die Einheiten für LUA-Bibliothek für Delphi und der Fall ist ziemlich wichtig für mich.

Angabe und Bereitstellung aller Details der Sache - Ich habe diese Funktion in C:

%Vor%

In Delphi habe ich so etwas:

LuaLibrary.pas

%Vor%

dtxLua.pas

%Vor%

und in anderen Einheiten wie Lua.pas verwende ich nur TLuaState von dtxLua.pas (weil LuaLibrary sperrig ist, dtxLua ist mein Wrapper), für viele nützliche und coole Dinge ...

    
HNB 21.02.2010, 13:12
quelle

4 Antworten

12

Ich vermute, dass der Prototyp für pushfstring etwa so aussieht:

%Vor%

Wenn nicht und stattdessen:

%Vor%

... dann sollte ich dich auch abdecken.

Wenn Sie in C einen Anruf von einer Variadic-Funktion an eine andere weitergeben müssen, sollten Sie va_list , va_start und va_end verwenden und die v -Funktion der Funktion aufrufen. Wenn Sie also printf selbst implementiert haben, könnten Sie vsprintf verwenden, um die Zeichenfolge zu formatieren - Sie können sprintf nicht direkt aufrufen und die Variadic-Argumentliste weiterleiten. Sie müssen va_list und Freunde verwenden.

Es ist ziemlich umständlich, C's va_list von Delphi zu behandeln, und technisch sollte es nicht gemacht werden - die Implementierung von va_list ist spezifisch für die Laufzeit des C-Compiler-Herstellers.

Aber wir können es versuchen. Angenommen, wir haben eine kleine Klasse - obwohl ich es zu einem Rekord für die Benutzerfreundlichkeit gemacht habe:

%Vor%

Mit diesem Datensatz können wir den Call-Frame manuell erstellen, der für verschiedene C-Aufrufe erwartet wird. Die Aufrufkonvention von c auf x86 besteht darin, Argumente von rechts nach links auf dem Stapel zu übergeben, wobei der Aufrufer aufräumt. Hier ist das Skelett einer generischen C-Aufrufroutine:

%Vor%

Nehmen Sie printf als Beispiel:

%Vor%

Der Aufruf der va_list Version ist etwas komplizierter, da der Speicherort des va_list Arguments genau dort platziert werden muss, wo es erwartet wird:

%Vor%

Anmerkungen:

  • Das obige erwartet x86 unter Windows. Microsoft C, bcc32 (Embarcadero C ++) und gcc übergeben va_list auf die gleiche Weise (ein Zeiger auf das erste variadische Argument auf dem Stapel), entsprechend meinen Experimenten, also sollte es für Sie arbeiten; aber sobald die x86 unter Windows-Annahme kaputt ist, erwarte, dass dies möglicherweise auch bricht.

  • Der Stapel wird getauscht, um die Konstruktion zu vereinfachen. Dies kann mit mehr Arbeit vermieden werden, aber das Übergeben von va_list wird auch schwieriger, da es auf die Argumente zeigen muss, als ob sie auf dem Stapel übergeben würden. Als eine Konsequenz muss der Code eine Annahme darüber machen, wie viel Stapel die aufgerufene Routine verwendet; In diesem Beispiel wird 8K angenommen, dies ist jedoch möglicherweise zu klein. Erhöhen Sie bei Bedarf.

Barry Kelly 21.02.2010, 17:53
quelle
4

Der Wrapper, den Sie schreiben wollen, ist in Free Pascal möglich, da Free Pascal zwei gleichwertige Deklarationen für externe Funktionen unterstützt:

Ссылка

also statt

%Vor%

Sie sollten

schreiben %Vor%

Update: Ich habe den gleichen Trick in Delphi versucht, aber es funktioniert nicht:

%Vor%     
kludg 21.02.2010 14:36
quelle
2

Ein "Array von const" ist eigentlich ein Array von TVarRec, welches eine spezielle Variante ist. Es ist nicht kompatibel mit Varargs, und Sie sollten in der Lage sein, die varargs-Funktion direkt ohne Wrapper aufzurufen.

    
Mason Wheeler 21.02.2010 13:28
quelle
1

Barry Kelly inspirierte mich, eine Lösung zu suchen, ohne den Stack zu ersetzen ... Hier ist die Lösung (wahrscheinlich könnte auch die Invoke von der RTTI-Unit statt RealCall_CDecl).

%Vor%     
HNB 22.02.2010 00:47
quelle