Script



  • Hi,

    ich bastel gerade noch etwas an einer Klasse, mit der man Funktionen registrieren kann und diese dann von außen aufgerufen werden können. Details sind eigentlich nicht so wichtig, ansonsten siehe http://www.c-plusplus.net/forum/290341-10 .

    Das eigentliche Problem:
    Intern habe ich nur drei Datentypen. (long, double, std::string). Jetzt stellt sich die Frage, wie die registrierbaren Funktionen aussehen könnten. Meine erste Idee war ganz simpel: ein std::stringstream. Da würde ich alle Parameter rein schieben und die Funktion selbst könnte ihre Rückgabewerte sogar auch rein schreiben, sodass ich ein simples Rückgabesystem hätte. Nur erscheint es mir irgendwie ziemlich blöde, alle Parameter umzuwandeln, zumal die aufgerufene Funktion sie dann ja eh wieder zurückwandeln muss. Da soll dann nur schnell ein int übergeben werden und der muss einmal nach String und zurück wandern. Ich denke, das Problem ist klar geworden.

    Zweite Idee: Ich habe nur drei Datentypen. Ich mache mir also einen

    struct Container
    {
      std::vector<long> ints;
      std::vector<double> floats;
      std::vector<std::string> strings;
    };
    

    Und Funktionen müssen dann diesen Parameter entgegennehmen und können einen dieser Typen zurückliefern. Das wären zwar drei verschiedene mögliche Funktionssignaturen, aber das wäre nicht so schlimm. Das Problem ist aber, dass so die Reihenfolge der Parameter verloren geht. Das kann natürlich nicht sein. Hat da irgendjemand eine Idee? Ich hoffe, mein Problem ist soweit klar geworden.



  • Wenn ich dich richtig verstanden habe (was sicherlich nicht zutrifft, siehe meine signatur),...

    ...dann machst du das so:

    #define RETTYPE void*
    #define ARGS void**
    typedef RETTYPE(FUNC)(ARGS);
    
    void* myfunc(void** args)
    {
        return (void*)&printf((char*)args[0], *((int*)args[1]));
    }
    
    int main()
    {
    
        FUNC* f = &myfunc;
        return *((int*)(f(  (void**){(void*)"ohai: %i\n", &20}  )));
    }
    
    // ungetestet.
    


  • siehe meine signatur

    🙂
    Ne geht nicht. Die Parameter die der Funktion mitgegeben werden werden von außen gestellt, was denkst du passiert, wenn sich da mal jemand einen Scherz erlaubt?



  • cooky451 schrieb:

    Hat da irgendjemand eine Idee?

    Tausende von Ideen. Und wenn ich Dein Problem kennen würde, könnte ich Dir auch auf Anhieb zehn sehr gut passende nennen.
    Aber Du machst ja eine verdammte Geheimsache daraus. Änderst alle paar Minuten die Aufgabe. Verbirgst den eigentlichen Plan hinter leeren Beispielen. So nicht!

    Wenn es eine Geheimsache ist, die so geheim ist, weil Du damit Geld verdienen willst, mußt Du auch für Hilfe zahlen.

    Wie machen das freiwillig und kostenlos. Durch Dein Herangehen opfern wir die zehnfache Zeit. Das geht nicht lange gut.



  • cooky451 schrieb:

    siehe meine signatur

    🙂
    Ne geht nicht. Die Parameter die der Funktion mitgegeben werden werden von außen gestellt, was denkst du passiert, wenn sich da mal jemand einen Scherz erlaubt?

    Also, die kann dein funktionsregisterklasse herausfiltern. Oder man guckt einfach ob etwas NULL ist oder so was. Wenn du einen parameter mit einem invaliden pointer einer normalen funktion übergibst explodiert diese auch...

    Falls du willst kannst du eine Args Klasse erstellen, die einen Args::Args(...) constructor hat.
    (also dieses va_args C zeugs.)

    EDIT#1: https://gist.github.com/1015162 ?



  • volkard schrieb:

    Änderst alle paar Minuten die Aufgabe. Verbirgst den eigentlichen Plan hinter leeren Beispielen. So nicht!

    Wenn es eine Geheimsache ist, die so geheim ist, weil Du damit Geld verdienen willst

    Tut mir ja leid, wenn ich diesen Eindruck erwecke, aber das ist nicht der Fall. Was heißt leere Beispiele? Ich versuche nur, das Posting nicht übermäßig aufzublähen. Wenn du keine Lust hast, mir zu helfen, niemand zwingt dich dazu. Wenn dein Unmut aber nur darauf beruht, dass ich zu wenig Informationen preisgebe, frag nach. Das ist bestimmt kein Geheimprojekt und ich werde versuchen jede Frage zufriedenstellend zu beantworten. Das Ziel ist immer noch Folgendes:

    int main()
    {
      Interpreter preter;
      preter.addFunction("foo", foo); // foo kann jetzt aus dem Script aufgerufen werden.
      preter.runScript(script); 
    }
    

    Und es ist eine Funktionssignatur für foo() gesucht, bei der ich
    - beliebig viele long, double, std::string, übergeben kann und mindestens einen dieser Datentypen zurückgeben kann (bzw. 3 Funktionssignaturen würden natürlich auch gehen. Für jeden return-Typ eine.)
    - Bei der ich nicht immer von Zahl nach String und zurück wandeln muss.
    - Die möglichst praktisch in der Anwendung der übergebenen Funktion ist, soll heißen, foo() sollte möglichst leicht an ihre Parameter kommen.
    - Die Reihenfolge der Parameter nicht verloren geht.

    Also, die kann dein funktionsregisterklasse herausfiltern.

    Das Ganze ist momentan so gedacht, dass ich erst mal alle Parameter die der Funktion im Script übergeben werden auslese und diese der Funktion dann auch übergebe. Was die dann damit macht ist ihre Sache. Nur funktioniert das mit void* natürlich nur bedingt, wenn im script steht foo(5); und foo aber denkt der Parameter wäre ein std::string.


Log in to reply