Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

LukasBanana

Alter Hase

  • »LukasBanana« ist der Autor dieses Themas

Beiträge: 1 097

Beruf: Shader Tools Programmer

  • Private Nachricht senden

1

12.06.2014, 12:15

C++ Funktion an eigene Virtuelle Maschine binden

In C++11 kann man recht komfortabel mit std::bind Funktionen (auch Member Functions) and Funktions-Objekte binden.
Wie aber kann man eine C++ Funktion an eine eigene Virtuelle Maschine binden?
Also wenn man seine eigene Script Sprache entwickelt.
Ohne eine Interoperabilität mit der 'Host'-Sprache wäre das ganze ja ziemlich Sinnfrei.
Bsp:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// Host side
class VirtualMachine
{
    public:
        void Bind(const FunctionObject& function, const std::string& scriptFunctionName);
        /* ... */
};
/* ... */
class Mouse
{
    public:
        static Mouse* Instance();
        bool IsButtonDown(int buttonIndex);
};
vm.Bind(&Mouse::Instance, "Mouse.Instance");
vm.Bind(&Mouse::IsButtonDown, "Mouse.IsButtonDown");

C-/C++-Quelltext

1
2
3
4
5
// Script side
extern class Mouse {
    public static Mouse Instance()
    public bool IsButtonDown(int buttonIndex)
}


Eine Interoperabilität mit ANSI C wäre vermutlich einfacher:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
// Host side
extern "C"
{

void* Mouse_Instance() { /* ... */ }
int Mouse_IsButtonDown(void* thisPtr, int buttonIndex) { /* ... */ }

}

vm.Bind(&Mouse_Instance, "Mouse.Instance");
vm.Bind(&Mouse_IsButtonDown, "Mouse.IsButtonDown");

Evrey

Treue Seele

Beiträge: 245

Beruf: Weltherrscher

  • Private Nachricht senden

2

12.06.2014, 13:34

Deine VM hat ja irgendein Standard-Verhalten, das sie von Funktionen erwartet. Zum Bleistift bekommen sie einen VM-State-Pointer und liefern als Ergebnis einen int, der angibt, wie viele Objekte die Funktion auf dem Stack als Rückgabewerte zurückgelassen hat. Das erfordert selbstverständlich Wrapper-Funktionen. Alternativ oder zusätzlich kann man auch Zeugs wie libFFI verbasteln.

Zitat

The libffi library provides a portable, high level programming interface to various calling conventions. This allows a programmer to call any function specified by a call interface description at run-time.
Du kannst dir zusätzlich den Quell-Code von AngelScript anschauen, das so weit ich gesehen habe völlig ohne Wrapper-Funktionen arbeitet.

Sei dir dabei im Klaren, dass Wrapper zwar lästiger zu implementieren, dafür allerdings schneller aufzurufen sind. Es sei denn natürlich, du hast einen supertollen JIT-Compiler, der aus der Verwaltungs- und Vorbereitungs-Arbeit in libFFI einen spezialisierten Funktionsaufruf bastelt.

C-/C++-Quelltext

1
2
3
4
int main(int _argc, char** _argv) noexcept {
  asm volatile("lock cmpxchg8b %eax");
  return 0;
} // ::main
(Dieses kleine Biest vermochte einst x86-Prozessoren lahm zu legen.)

=> Und er blogt unter Hackish.Codes D:

Beiträge: 1 223

Wohnort: Deutschland Bayern

Beruf: Schüler

  • Private Nachricht senden

3

12.06.2014, 15:11

So ganz verstehen tu ich das Problem ja nicht. Du hast doch einen Funktionszeiger auf die fragliche Funktion. Den kannst du doch ganz einfach aufrufen und verwenden und wenn es dich Glücklich macht, auch an so ein "std::function" binden.
Wegen Calling-Convention...
Da solltest du natürlich direkt eine Kompatible verwenden. Du kannst ja auch Funktionszeiger explizit mit Fastcall, Stdcall, oder Ccall markieren um es genau zu spezifizieren. Ich denke nicht, das man sich dafür irgendeine Lib holen muss.

LukasBanana

Alter Hase

  • »LukasBanana« ist der Autor dieses Themas

Beiträge: 1 097

Beruf: Shader Tools Programmer

  • Private Nachricht senden

4

12.06.2014, 23:38

Ich will das meine VM C++ Funktionen aufrufen kann, die der Script Programmierer mit der VM an die Script Funktionen gebunden hat.
Diese C++ (und auch Script) Funktionen können natürlich immer unterschiedliche Signaturen haben (also unterschiedliche Parameter).
Ich sehe hier momentan nur die Möglichkeit, dass meine VM mit hand geschriebenem Assembler (x86 z.B.) diese C++ Funktionen aufruft,
weil zur Compiler Zeit (des VM C++ Codes) nicht bekannt ist, welche Funktionen an die Scripte gebunden werden.
Die VM muss aber die korrekten Parameter auf den Stack legen, wenn die gebundene C++ Funktion aufgerufen werden soll.

Evrey

Treue Seele

Beiträge: 245

Beruf: Weltherrscher

  • Private Nachricht senden

5

12.06.2014, 23:50

Wie gesagt: libFFI.

C-/C++-Quelltext

1
2
3
4
int main(int _argc, char** _argv) noexcept {
  asm volatile("lock cmpxchg8b %eax");
  return 0;
} // ::main
(Dieses kleine Biest vermochte einst x86-Prozessoren lahm zu legen.)

=> Und er blogt unter Hackish.Codes D:

Beiträge: 1 223

Wohnort: Deutschland Bayern

Beruf: Schüler

  • Private Nachricht senden

6

12.06.2014, 23:54

Zitat

Compiler Zeit (des VM C++ Codes) nicht bekannt ist, welche Funktionen an die Scripte gebunden werden.

Dann generiere doch einfach einen indirekten Funktionsaufruf. So wie in nativen C++ Funktionszeiger aufruft oder "virtual".

Zitat

Die VM muss aber die korrekten Parameter auf den Stack legen

Die VM muss natürlich solchen Maschinencode generieren, dass sie die Calling Convention trifft. Dafür müssen zur Compilezeit die Parametertypen bekannt sein, aber das sollten sie sowieso. Funktionen mit der selben Calling Convention und den selben Parametern, erwarten grundsätzlich alle die selben Daten in Registern und dem Stack in genau gleicher Form.

LukasBanana

Alter Hase

  • »LukasBanana« ist der Autor dieses Themas

Beiträge: 1 097

Beruf: Shader Tools Programmer

  • Private Nachricht senden

7

13.06.2014, 15:07

Wie gesagt: libFFI.

Stimmt, das sieht nach dem aus, was ich suche.
Danke.

Werbeanzeige