Funktionen, die als String vorliegen aufrufen



  • Ich weiß, der Titel ist blöd, man kann das Problem nicht in eine Zeile fassen.

    Folgendes:

    Ich habe verschiedene Headerdateien einer dll. Zum Beispiel

    Header.hpp

    ...
    LIntExport Herror decode_2d_bar_code(const HTuple&,const HTuple&,const HTuple&);
    LIntExport Herror get_2d_bar_code_pos(const Hobject&,const Hobject&,);
    LIntExport Herror find_2d_bar_code(const Hobject&,Hobject*);
    LIntExport Herror gen_2d_bar_code_descr(const HTuple&,const HTuple&,HTuple*);
    LIntExport Herror discrete_1d_bar_code(const HTuple&,const HTuple&,HTuple*);
    ...
    

    Daraus hole ich mir für jede Funktion den Namen, Rückgabewert und die Parameter. Die habe ich also als Strings schon vorliegen.

    Wenn ich jetzt in meinem Programm eine dieser Funktionen auswähle, möchte ich sie aufrufen. Ich hatte mir das so in etwa vorgestellt:

    dll-wrapper.cpp

    // In argc steht die Anzahl der Strings, die ich übergebe.
    // argv hat etwa folgenden Aufbau: func_name, return_value, param_type_1, 
    // param_1, param_type_2, param_2, .., param_type_n, param_n
    void call_dll_function(int argc, int argv[])
    {
        // Zuerst werden die Parameter ausgewertet (Typ und Wert)
        if(param_typ == "unsigned char") {
            ...
        }
    
        // Wenn ich alles hingebogen habe, möchte ich die entsprechende Funktion 
        // jetzt aufrufen und das Ergebnis zurückliefern
        ???
    }
    

    Ich hoffe, ich konnte rüberbringen, was ich machen möchte. Die einzelnen Funktionen hardcoden geht nicht, da es jetzt schon über 800 sind und sich ständig ändern können.

    Hat jemand einen Vorschlag, wie man das realisieren könnte?



  • Wenn alle Funktionen die selbe Parameterliste hätten, könntest du dir einen entsprechenden Funktionspointer definieren und dir per LoadLibrary und GetProcAdress() die passende Funktion besorgen.

    Ansonsten solltest du mal erklären, was du eigentlich dort vorhast.



  • Ich weiß, ist ganz schön verworren die Aufgabe.

    Sinn und Zweck:

    Die Libraries, die vorliegen sind Bildverarbeitungsroutinen. Mit vielen hundert Funktionen. Ich möchte (oder besser muss) nun aus LabVIEW (grafische Prog-Sprache) zur Laufzeit heraus dynamisch auf diese Funktionen zugreifen. In LabVIEW soll ein User alle verfügbaren Funktionen angezeigt bekommen und sich diese nach belieben aneinanderreihen. DLL-Funktionen werden in LabVIEW in einem Call-Library-Node aufgerufen. Da stellt man die Funktion ein, die Parameter und so weiter. Leider kann man das nicht dynamisch zur Laufzeit ändern.
    Wenn ich alle DLL-Funktionen nicht hardcoden möchte, brauche ich einen Mechanismus, der mir die Dinger dynamisch identifiziert und aufruft. Ich dachte halt, dass ich im LabVIEW immer nur eine Funktion aufrufe (meinen dll-Wrapper), der dann die Aufrufe an die Bibliotheken weiterleitet.
    Denn in LabVIEW geht es halt wie gesagt nicht. Deswegen wollte ich das in C/C++ auslagern.

    Leider sind die Parameterlisten auch nicht identisch. Mal gibts 3 Parameter, mal 27. Immer mit den verschiedensten Datentypen.



  • Du brauchst schon eine einheitliche Parameterübergabe, da du ja dann eine konkrete Funktion mit entsprechenden Parametern aufrufen mußt. Die verschiedenen Funktionsnamen sind nicht das Problem, da wie schon geschrieben, diese der Funktion "LoadLibrary" bzw. "GetProcAddress" übergeben werden, aber den Rückgabewert mußt du dann auf einen passenden Funktionsprototypen casten, z.b.

    const char *cFuncname = "myfunc"; // oder als Parameter
    
    typedef void (*MyFunc)(int, unsigned char, const char *);
    
    HINSTANCE hInstLib = LoadLibrary("libname");
    
    MyFunc func = (MyFunc)GetProcAddress(hInstLib, cFuncname);
    if(func)
       (*func)(0, 'x', "hello"); // oder hier auch wieder dynamische Werte, aber die Anzahl der Parameter mußt du fest coden
    

    Eine andere Möglichkeit wäre, wenn du direkt den Aufrufstack erzeugst und die entsprechende Funktion dann aufrufst (am besten in Assembler).



  • hm... also zusammengefasst: du hast eine oder mehrere Dlls mit verschiedenen Funktionen, die auch alle verschiedene Parameter erwarten?
    Und die willst in deinem Programm mittels einer Funktion wie

    CallDll(string fnName, parameterliste...)

    diese funktionen aus der Dll aufrufen?

    das is übel, glaubich..

    Ich denke, dir bleibt nichts anderes übrig, als (wenigstens die Funktionsnamen mit parameterliste hardzucoden.)

    Ich würde dann glaub ich versuchen, für jede funktion eine Klasse zu schreiben, die genau diese funktion wrappt, oder eine Klasse für alle Funktionen, die die dinger wrappt, so dass du dann sozusagen die Klasse als funktion hast, den Rest macht die Klasse für sich. Die Klassen müssen aber trotzdem wissen, wie ihre Funktion heißt und welche Parameter die erwartet. Und die muss dann auch mittels GetProcAddress den Funktionspointer aus der Dll laden... aber so müsste es gehen.



  • Th schrieb:

    Eine andere Möglichkeit wäre, wenn du direkt den Aufrufstack erzeugst und die entsprechende Funktion dann aufrufst (am besten in Assembler).

    das is ne coole Idee, aber da musst due die aufrufkonventionen kennen und so, da kann auch mehr schiefgehen als mit loadlibrary und co



  • Das ist in dem Fall nicht nur ne coole Idee, sondern die einzige saubere Lösung (ohne Neuschreiben von sehr viel Code).
    Die Aufrufkonvention rauszufinden ist ja kein Problem.

    Wenn du mal wieder sowas hast, dann wäre es einfacher die Funktionen in einer Skriptsprache wie LUA zu schreiben, dann ist das ganze kein Problem 🙂



  • Mmh, also das mit dem Aufrufstack muss ich mir dann mal anschauen. Gibts da gute Links oder Doku dazu?

    @Maxi
    Die Sache mit den extra-Klassen für jede Funktion wollte ich gerade vermeiden. Denn in der jetzigen Bibliothek sind 6981 Funktionen. Und es ist durchaus möglich, dass die Bibliothek demnächst getauscht wird. Sonst könnte ich es auch im LabVIEW hardcoden.

    Wie ich mir schon dachte, ist die Aufgabe ziemlich Hardcore... Mal schauen, ob ich irgendwie einen Weg finde.

    Erstmal Danke an alle.



  • Steht dir der Sourcecode von dieser Labview-Sprache zur Verfügung? Weil dann kannst du einfach ein Languagebinding programmieren. manche benutzen dafür auch Boosts Sprachbinder, damit wurde schon Python und Ruby an C++ mittels Boost gebunden.

    Das Problem an der ganzen Thematik (hat jetzt nichts speziell mit Boost zu tun) ist, das du sehr viel zu Fuss erledigen mußt, damit deine API auf beiden Seiten angesprochen werden kann. Das wirst du mit drei Zeilen C++ Code nicht hinbekommen.



  • Artchi schrieb:

    Steht dir der Sourcecode von dieser Labview-Sprache zur Verfügung?

    Nee, dass ist ne professionelle Programmiersprache (4000 € pro Lizenz) für den technischen Bereich. Bin wegen Firmenpolitik leider darauf angewiesen.


Anmelden zum Antworten