Gekapselter DLL Aufruf

 

Guten Morgen liebe Com,


ich habe folgendes Problem, ich binde eine Dll in ein EA ein, dieses funktioniert auch ganz gut,
ich kann auch mehrere Klassen ansprechen innerhalb der DLL, allerdings wenn ich nun von der
eingebetteten DLL eine andere DLL aufrufe, funktioniert es nicht mehr.


// Eingebettete DLL in den EA
partial class Class1
    {
        [DllExport("AddText", CallingConvention = CallingConvention.StdCall)]
        [return: MarshalAs(UnmanagedType.LPWStr)]
        public static string test([MarshalAs(UnmanagedType.LPWStr)] string a)
        {
            string b = string.Empty;
            try
            {
                string c = Class2.writeFile(a);
            }
            catch (Exception) { }
            using (StreamWriter wr = new StreamWriter(@"d:\test.txt", true))
            {
                wr.WriteLine(a);
            }
            return a;
        }
    }

    //Funktioniert nur, wenn Class3 nicht aufgerufen wird (Class3 ist eine weitere gekapselte DLL)
    public class Class2
    {
        public static string writeFile(string msg)
        {
            //Class3.writeFile(msg);
            using (StreamWriter wr = new StreamWriter(@"d:\test2.txt", true))
            {
                wr.WriteLine(msg);
            }
            return msg;

        }
    }


    //Die gekapselte DLL
    public class Class3
    {
        public static string writeFile(string msg)
        {
            MessageBox.Show(msg);
            using (StreamWriter wr = new StreamWriter(@"d:\test3.txt", true))
            {
                wr.WriteLine(msg);
            }
            return "class3";
        }
    }

    Wenn ich nun die Gekapselte DLL(Class3) direkt in Class1 anspreche, bekomme
    ich die Errormeldung "2018.01.31 08:14:18  Unhandled exception 0xE0434352" im Terminal.
    Umgehe ich dies, mit der Class2, so bekome ich keine Fehlermeldung mehr, jedoch,
    sobald ich Class3 in Class2 aufrufe wird die Funktion aus Class2 nicht mehr ausgeführt,
    ohne Fehlermeldung.

    Kann mir da jemand auf die Sprünge helfen?
 

Ich kann Dir da nicht wirklich helfen, aber kannst Du die verschachtelten der Klassen nicht vereinfachen?

Was ist, wenn  Dur alle  Deine Klassen mit :: "globalisierst"?

ich weiß nur, dass nicht alles, was in C++ funktioniert auch in MQL4/5 geht!

 
Carl Schreiber:

Ich kann Dir da nicht wirklich helfen, aber kannst Du die verschachtelten der Klassen nicht vereinfachen?

Was ist, wenn  Dur alle  Deine Klassen mit :: "globalisierst"?

ich weiß nur, dass nicht alles, was in C++ funktioniert auch in MQL4/5 geht!

Das eigentliche Problem, warum ich Auslagern möchte in eine zweite DLL ist, dass ich jedesmal, wenn ich teste, das Terminal schließen muss

um die DLL auszutauschen, da ich sonst Zugriffskonflikte bekomme. Auf die zweite DLL greift das Terminal nämlich nicht zu und ich hätte

dieses Problem gelöst, nur leider habe ich nun das Problem, dass sich aus der zweiten DLL keine Funktionen aufrufen lassen, nicht einmal

leere Funktionen. Dies bereitet mir gerade echtes Kopfzerbrechen. Ich habe schon zig Seiten/Foren durchstöbert und gesucht aber leider

naadaa ...

Und es ist C# und kein C++ :)

Und dann denke ich da noch weiter, auf die zweite DLL könnte man noch ein anderes Programm zugreifen lassen, für Auswertungen und so,

ich möchte ungern alles in MQL schreiben.

 

Das könnte schon der Haken liegen, ich meine es müssen ALLE dlls zu copelierzeit geladen sein.

Dynamisch nachladen kann der MT5 nicht.

Ich such mal den Artikel dazu ...

 

Aufruf der Importfunktionen

für Import der Funktionen während der Ausführung des mql5-Programmes wird frühe Bindung verwendet. Das bedeutet wenn es im Programm Aufruf der Importfunktion gibt, wird der entsprechende Modul (ex5 oder dll) beim Programmladen geladen. Bibliotheken MQL5 und DLL Werden im Thread des Aufrufmoduls durchgeführt.  

Es ist nicht empfehlenswert, den vollstaendig bestimmten Namen des geladenen Moduls der Art Drive:\Directory\FileName.Ext verwenden. Bibliotheken MQL5 werden vom Ordner terminal_dir\MQL5\Libraries ausgeladen. Wenn Bibliothek nicht gefunden wurde, versucht man, Bibliothek vom Ordner terminal_dir\experts herunterzuladen.

Systembibliotheken werden nach Regeln (DLL) des Operationssystems geladen. Wenn die Bibliothek schon geladen wird (zB. von anderen Experten oder aus anderem Client-Terminal, das parallel startet) wird die schon  geladene Bibliothek aufgerufen.Anderenfalls erfolgt die Suche in der Folge:  

  1. Verzeichnis, von dem das dll importierende Modul abgelaufen wurde. Unter Modul wird Expert, Script, Indikator oder Bibliothek EX5 verstanden;
  2. Verzeichnis Katalog_Data_Terminals\MQL5\Libraries (TERMINAL_DATA_PATH\MQL5\Libraries);
  3. Verzeichnis, von dem das Client-Terminal MetaTrader 5 gestartet wurde;
  4. Systemverzeichnis;
  5. Verzeichnis Windows;
  6. Laufendes Verzeichnis;
  7. Verzeichnisse, die in Systemvariable PATH aufgelistet sind.

Wenn die Bibliothek  DLL eine andere DLL in ihrer Arbeit verwendet, dann kann die erste DLL beim Fehlen der zweiten DLL nicht geladen werden.

Vor dem Laden des Experten (Script, Indikator) wird die gesamte Liste aller Bibliothekmoduln EX5 gebildet, die sowohl von dem geladenen Experten(Script, Indikator), als auch von der Bibliothek dieser Liste zu verwenden gedacht. So erfolgt das einmalige Laden der mehrmalig verwendeten Bibliothekmoduln EX5. Bibliotheken verwenden vorbestimmte Variablen des Experten (Script, Indikator), der sie aufgerufen hat.  

Suche der importierten Bibliothek wird in der Folge durchgeführt:

  1. Verzeichnis, Pfad zu dem in Bezug auf Verzeichnis des importierenden EX5 Experten (Script, Indikator)  vorgegeben wird;
  2. Verzeichnis Katalog_Terminals\MQL5\Libraries;
  3. Verzeichnis MQL5\Libraries im Gesamtverzeichnis aller Client-Terminals MetaTrader 5(Common\MQL5\Libraries).

Funktionen, die aus DLL in mql5-Programm , importiert werden, müssen Windows API Abkommen garantieren. Für Garantieren dieses Abkommens wird im Ausgangstext der Programme, die mit den Sprachen  C oder C++ geschrieben werden, das Schluesselwort  __stdcall verwendet, das für Compiler der Gesellschaft  Microsoft(r) spezifisch ist. Das Abkommen ist dadurch charakterisiert:

  • ausrufende Funktion (hier mq5-Programm) muss "sehen" Prototyp der aufgerufenen Funktion (importierten aus DLL), um Parameter zum Stack richtig zusammenzustellen;  
  • ausrufende Funktion (hier mql5-Programm) stellt Parameter auf Stack in umgekehrter Reihenfolge, von rechts nach links - gerade in dieser Reihenfolge liest die importierte Funktion die ihr übertragenen Parameter ein;
  • Parameter werden nach Wert übertragen ausser deneb, die explizit durch Referenz übertragen werden (in diesem Fall sind es Zeilen)
  • Importfunktion, klaert Stack selbst ab beim Einlesen der ihr übertragenen Parameter.

Beim Beschreiben des Prototyps der Importfunktion können Parameter mit Defaultwerten verwendet werden.

Falls die entsprechende Bibliothek nicht in der Lage war, geladen zu werden oder es ist untersagt,  DLL zu verwenden oder die importierte Funktion nicht gefunden war - stoppt Expert seine Arbeit mit der entsprechenden Nachricht  "expert stopped" im Journal. Dabei wird Expert nicht ablaufen lassen, bevor er neuinitialisiert wird. Expert kann neuinitialisiet werden im Ergebnis der Umcompilierung oder der Öffnung der Eigenschaften der Tabelle und Drücken der Schaltfläche OK.

Parameterübertragung

Alle Parameter der einfachen Typen werden nach Wert übertagen, wenn nicht explizit angegeben wird, dass sie durch Refernz übertragen werden. Bei der Übertragung einer Zeile wird Pufferadresse der kopierten Zeile übertragen; wenn eine Zeile durch Refenz übertragen wird, wird in die aus DLL importierte Funktion Pufferadresse gerader dieser Zeile Zeile ohne Kopieren übertragen.

Strukturen, die dynamische Felder, Zeilen, Klassen, andere komplizierte Strukturen, aber auch statische oder dynamische Felder der aufgelisteten Objekte enthalten, können nicht als Parameter in eine importierte Funktion übertragen werden.

Bei der Übertragung des Feldes in  DLL wird immer (unabhängig von der Flagge AS_SERIES) die Adresse des Pufferanfangs übertragen. Funktion innerhalb DLL weiss nichts von der Flagge  AS_SERIES, das übertragene Feld ist ein statisches Feld der unbekannten Laenge, für Spezifizieren der Feldgroesse verwenden Sie einen zusätzlichen Parameter.

 

Das ist soweit gut und schön, ich lese daraus, wenn die zweite dll nicht da ist, kann die Erste nicht geladen werden.

Da die dll aber geladen wird und Funktionen aufruft und durchführt, ist die Zweite auch da.

Ich habe spaßeshalber die zweite dll in den EA eingebunden, läuft prima, beim Direktaufruf.

Aber der Aufruf von dll zu dll klappt immer noch nicht. Mir fehlt da die Logic, da ich letztendlich

das ganze Framework ansprechen kann, sprich MessageBoxen erzeugen etc. Macht das Terminal alles

mit, sonst würde auch der Steamwriter nicht funktionieren, da mache ich ja auch nichts anderes als

andere Klassen und dlls mit einbinden um die Funktionen nutzen zu können.

Vielleicht muss ich auch die zweite dll in Windows global verfügbar machen, das wäre noch eine Idee.

Mein Kopf platzt gleich. ...

 

Achso , das habe ich dann falsch verstanden.

Ich dachte du möchtest wenn der EA läuft noch an der 2. DLL arbeiten und die dann später dazu haben.

Vielleicht hat jemand anderes noch ein Tip

gruß

 

Nein, zur RunTime am Object scripten ist immer eine ganz ganz schlechte Idee. :)

Habe gerade den Support hier angeschrieben, dieses Problem ist mir gerade zu Hardcore für mein Kopf, da alles andere ja

funktioniert. Falls jemand eine Idee hat, immer her damit, habe die dll auch schon in Windows global gesetzt ... nichts.

Durch sowas kann man sich auch das Wochenende versauen. :D

Wie kann man hier eigentlich Smilies einfügen, bin seit heute ja neu, noch kein Button für gefunden.

 
RokaDransal:

Nein, zur RunTime am Object scripten ist immer eine ganz ganz schlechte Idee. :)

Habe gerade den Support hier angeschrieben, dieses Problem ist mir gerade zu Hardcore für mein Kopf, da alles andere ja

funktioniert. Falls jemand eine Idee hat, immer her damit, habe die dll auch schon in Windows global gesetzt ... nichts.

Durch sowas kann man sich auch das Wochenende versauen. :D

Wie kann man hier eigentlich Smilies einfügen, bin seit heute ja neu, noch kein Button für gefunden.

Russland ist mächtig oldscool ..gewöhn dich dan

Grund der Beschwerde: