Jump to content
Tom Next - Daytrading Community

Free Pascal


mtbf40

Recommended Posts

Hallo an alle Free-Pascaler,

 

habe folgendes Problem:

ich möchte eine dll etwickeln die mir alle Trades aus der History in eine GUI schreibt. Mit den Daten möchte ich dann weiterarbeiten.

 

zu Testzwecken habe ich bis jetzt folgendes:

 

DLL:

library orderhist;

{$mode objfpc}{$H+}

uses
 Classes
 { you can add units after this };

type
 TOrderHist = array[0..7] of string;

// function parameters declared as var will accept pointers.
procedure VarsByReference(var oh: TOrderHist) ; stdcall;
var
 Datei : TextFile;
begin
 // now let's make some changes to the variables
 Assign (Datei, 'C:/Tools/mt4log.log');
 ReWrite (Datei);
 writeln(Datei,oh[7]);
 close(Datei);
end;

exports
 VarsByReference;

begin
end.

 

MT4:

//#include <common_functions.mqh>


#import "orderhist.dll"
  void VarsByReference(string& oh[]);
#import


int start()
{
// retrieving info from trade history
  int k,i,hstTotal=HistoryTotal();
  int HistoryOrderType; 
  int HistoryOrderTicket; 
  int HistoryOrderCloseTime;
  double HistoryOrderClosePrice;
  int HistoryOrderOpenTime;
  double HistoryOrderOpenPrice;
  double HistoryOrderOpenProfit;
  double HistoryOrderOpenStopLoss;

  string HistoryOrder[8];

  for(i=0;i<hstTotal;i++)
  {
 	if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)==false)
 	{
		Print("Access to history failed with error (",GetLastError(),")");
		break;
 	}

HistoryOrder[0]=OrderCloseTime();
HistoryOrder[1]=OrderClosePrice();
HistoryOrder[2]=OrderOpenTime();
HistoryOrder[3]=OrderOpenPrice();
HistoryOrder[4]=OrderProfit();
HistoryOrder[5]=OrderStopLoss();
HistoryOrder[6]=OrderTicket();
HistoryOrder[7]=OrderSymbol();


int count=ArraySize(HistoryOrder);
for(k=0; k<count; k++)
{
  		//log("OrderHistoryOutput_"+k,HistoryOrder[k]);
  		Print("blabla_"+k);
}
	VarsByReference(HistoryOrder);
  }
}

 

Resultat:

die DLL legt zwar die log-Datei an!! schreibt aber nur irgend welche Zeichen rein und blässt die Datei auf 100'erte MB's auf - ich muß dann schleunigst MT4 schließen, sonst legt die mir noch den Server lahm. Das mql-Skript läuft als Script im MT4.

 

Wer weiß was hier schief läuft??

 

ProgrammIDE ist Lazarus

Edited by mtbf40
Link to comment
Share on other sites

Hi,

 

ich würde mir erstmal "hstTotal" anzeigen lassen, vllt läuft da schon was schief und die Schleife wird zu gross.

 

Also erstmal schauen, ob die Schleife korrekt arbeitet.

 

Dann könnte bei der Übergabe des Strings was schief laufen.

 

Muss man Step bei Step eingrenzen.

 

 

Link to comment
Share on other sites

Hi,

 

ich würde mir erstmal "hstTotal" anzeigen lassen, vllt läuft da schon was schief und die Schleife wird zu gross.

 

Also erstmal schauen, ob die Schleife korrekt arbeitet.

 

Dann könnte bei der Übergabe des Strings was schief laufen.

 

Muss man Step bei Step eingrenzen.

 

die Schleife funktioniert - habe mir das mit dem Logging ausgeben lassen - über <common_functions.mqh>

was ich jetzt gesehen habe ist, die DLL schreibt nur Space-Zeichen (Hex 20)

Link to comment
Share on other sites

OK,

 

dann schreib in HistoryOrder[7] mal was anderes rein, weil nur der String wird ja in die Datei geschrieben.

 

HistoryOrder[7] = "Test"

//HistoryOrder[7]=OrderSymbol();

oder sowas, wenn dann nur Leerzeichen drin stehen, stimmt was mit "OrderSymbol()" nicht, bzw mit dem Ticket.

Link to comment
Share on other sites

Hallo an alle Free-Pascaler,

 

habe folgendes Problem:

ich möchte eine dll etwickeln die mir alle Trades aus der History in eine GUI schreibt. Mit den Daten möchte ich dann weiterarbeiten.

 

Bin kein Free-Pascaler.

Hätte evtl. einen anderen Lösungsansatz: erstmal eine .csv-Datei mit Hilfe der MQL-Filefunktionen erzeugen.

 

Danach manuell die Pascal-DLL aufrufen, die die .csv-Datei einliest.

Erst wenn das klappt dann evtl. Erweitern auf direkten Aufruf der DLL aus dem MQL-Skript.

Link to comment
Share on other sites

Ich bin mal zu faul ne Erklärung zu schreiben.

Ich denke 7bit kann das ein wenig besser.

 

http://www.forexfactory.com/showthread.php?t=219576

 

Schaue mal nach 32bit und 64bit.

Schaue mal nach passing value by reference.

Value kann in diesem Fall ein Integer, Double, String

bzw. auch ein Array sein.

Schaue auch mal hier: http://www.lazarus.freepascal.org/index.php?topic=13607.0 und http://wiki.lazarus.freepascal.org/Passing_Pascal_Types_to_C_Routines.

  • Upvote 1
Link to comment
Share on other sites

erst einmal Danke für die Antworten - muß jetzt erst einmal alles sondieren - wo ich wahrscheinlich das Problem sehe ist, das die dll eine 64bit-compillierte ist. Muß jetzt mal die 32bit Version von Lazarus installieren, denn auf meinem Laptop und auf dem MT4 Server laufen jeweils Win7 64bit mit Lazarus 64bit

 

FALLS jemand eine Lösung "geschrieben" hat - möge er sie nur für sich behalten!! :plorar1::spank:

Link to comment
Share on other sites

so - habe jetzt Lazarus-Versionen für 32bit und 64bit parallel installiert!

DLL 32bit kompilliert und peng Datei >1GB :schimpf:

 

was ich bis jetzt herausgefunden habe ist folgendes: die meisten Konstrukte von DLL<-> MT4 laufen so: MT4 ruft Funktion aus DLL auf-> DLL macht was -> gibt Ergebnis zurück an MT4

ich möchte aber dies machen: MT4 ruft Funktion aus DLL auf-> DLL macht was -> schreibt Ergebnisin eine Datei

 

Ich habe keinen blassen Schimmer warum er nur 0x20 Zeichen reinschießt. :washer:

 

Habe das ganze mal mit dem Procmon (Sysinternals) verfolgt - da sieht man wie die Zeichen in nano-Sekunden reinschießen. Ich muß dann MT4 schließen um nicht meinen Server lahm zu legen. Ich habe den Eindruck das der MT4 das Skript "hält", obwohl es ja ein Skript ist und nur einmal aufgerufen wird und das wars dann. Denn das Skript wird erst geschlossen, wenn ich MT4 (terminal.exe) schließe - und zwar als letzte Aktion!!!

Würde ja gern mal einen Screenshot zeigen - kann aber nix hochladen Fehler 407

Link to comment
Share on other sites

Da wir uns ja im rechtsfreien Raum bewegen (kein Mod anwesend)

Was für einen Datei Typ willst du hochladen ?

 

jpeg, PNG usw. geht bei mir einwandfrei.

 

png-File - 299k

 

 

mt4_dll.png

Das hochladen dieser Datei wurde übersprungen. (Fehler IO)

 

 

Edited by mtbf40
Link to comment
Share on other sites

Dez Hex Okt ASCII

32 0x20 040 SP

 

Code 0x20 (SP) ist das Leerzeichen.

Da geht immer noch etwas schief.

Es gibt zwei Ansätze Daten zws. zwei

unterschiedlichen Systemen zu schaufeln.

 

Pass By Reference :
In Pass by reference address of the variable is passed to a function. Whatever changes made to the formal parameter will affect to the actual parameters
- Same memory location is used for both variables.(Formal and Actual)-
- it is useful when you required to return more then 1 values
Pass By Value:
- In this method value of the variable is passed. Changes made to formal will not affect the actual parameters.
- Different memory locations will be created for both variables. 
- Here there will be temporary variable created in the function stack which does not affect the original variable. 

 

Metatrader ist 32bit und es wird wohl keine 64bit Version geben. Wenn dem nicht so ist, nehme ich diese Aussage zurück.

Du mußt auf jedem Fall Pascal mit 32bit kompelieren.

 

Warum schreibt du dir nicht erstmal eine kleine C-Anwendung. Metatrader ist, glaube ich, in Delphi geschrieben. Vielleicht

auch mal ein kleines Delphi Programm. Beispiele gibt es sicher im Netz.

Link to comment
Share on other sites

Metatrader ist 32bit und es wird wohl keine 64bit Version geben. Wenn dem nicht so ist, nehme ich diese Aussage zurück.

Du mußt auf jedem Fall Pascal mit 32bit kompelieren.

ist doch alles mit 32bit kompiliert !! :palomitas:

 

Warum schreibt du dir nicht erstmal eine kleine C-Anwendung. Metatrader ist, glaube ich, in Delphi geschrieben. Vielleicht

auch mal ein kleines Delphi Programm. Beispiele gibt es sicher im Netz.

 

Wenn Metatrader in Delphi programmiert ist, sollte es auf jeden Fall reibungslos funktionieren, denn Freepascal (Lazarus) ist nahezu Delphi kompatibel!

Link to comment
Share on other sites

Wer weiß was hier schief läuft??

1. Dein rewrite überschreibt die Datei immer wieder. Wahrscheinlich willst du doch die Datei ergänzen, oder?

2. Die String-Typen sind nicht kompatibel. Und ein Array von Strings ist eine ganz andere Hausnummer (Zeiger auf eine Liste von Zeigern).

 

Ich habe etwa einen Monat gebraucht, um Strings auszutauschen (Delphi-DLL) und ich bezeichne mich eigentlich als recht guten Programmierer.

 

Was ist ein String? Die Variable beinhaltet einen Zeiger auf das erste Byte. Jedes Byte repräsentiert einen character. Der String endet mit Byte-Wert 00. Blöd ist nur, dass Free Pascal oder Delphi unter dem Typ String etwas vollkommen anderes verstehen. Das erste Byte ist hier die Länge des Strings. Dann folgen die Characters. Seit einigen Versionen werden die jedoch Unicode gespeichert, sodass ein Zeichen einem Byte ist.

 

Lösung:

Übergib einen Zeiger auf das erste Zeichen. Dies wird durch den "normalen" string-Typ von MT4 veranlasst. Auf DLL-Seite empfängst du diesen Zeiger und baust dir deinen String byteweise selbst zusammen. Danach kannst du frei agieren. Das mit dem String-Array würde ich lassen, da es noch komplexer wird und auch anderweitig abbildbar wäre.

 

Möchtest du selber probieren oder Codebeispiele? :palomitas:

  • Upvote 2
Link to comment
Share on other sites

1. Dein rewrite überschreibt die Datei immer wieder. Wahrscheinlich willst du doch die Datei ergänzen, oder?

2. Die String-Typen sind nicht kompatibel. Und ein Array von Strings ist eine ganz andere Hausnummer (Zeiger auf eine Liste von Zeigern).

 

Ich habe etwa einen Monat gebraucht, um Strings auszutauschen (Delphi-DLL) und ich bezeichne mich eigentlich als recht guten Programmierer.

 

Was ist ein String? Die Variable beinhaltet einen Zeiger auf das erste Byte. Jedes Byte repräsentiert einen character. Der String endet mit Byte-Wert 00. Blöd ist nur, dass Free Pascal oder Delphi unter dem Typ String etwas vollkommen anderes verstehen. Das erste Byte ist hier die Länge des Strings. Dann folgen die Characters. Seit einigen Versionen werden die jedoch Unicode gespeichert, sodass ein Zeichen <> einem Byte ist.

 

Lösung:

Übergib einen Zeiger auf das erste Zeichen. Dies wird durch den "normalen" string-Typ von MT4 veranlasst. Auf DLL-Seite empfängst du diesen Zeiger und baust dir deinen String byteweise selbst zusammen. Danach kannst du frei agieren. Das mit dem String-Array würde ich lassen, da es noch komplexer wird und auch anderweitig abbildbar wäre.

 

Möchtest du selber probieren oder Codebeispiele? :palomitas:

 

danke für die Hinweise. :cura1-1:

habe jetzt mal folgendes versucht:

Änderungen in DLL: cdecl deklariert und Type PChar

 

Änderungen in MT4:

HistoryOrder[0]="Test";

HistoryOrder[1]="Test1";

 

library orderhist;

{$mode objfpc}{$H+}

uses
 Windows,Classes
 { you can add units after this };

type
 TOrderHist = array[0..7] of PChar;

// function parameters declared as var will accept pointers.
//procedure VarsByReference(var oh: TOrderHist) ; stdcall;
procedure VarsByReference(var oh: TOrderhist) ; cdecl;
var
 Datei : TextFile;
begin
 // now let's make some changes to the variables
 Assign (Datei, 'C:/Tools/mt4log.log');
 ReWrite (Datei);
 writeln(Datei,oh[1]);
 close(Datei);
end;

exports
 VarsByReference;

begin
end.

 

Resultat: die DLL schreibt jetzt zumindest Test!! rein - trotzdem alles merkwürdig - vor allem: wieso "funktioniert" es plötzlich mit cdecl?? :white_flag:

 

Fazit: würde gern mal ein paar Code-Schnipsel bekommen

 

mtbf40

Link to comment
Share on other sites

Fazit: würde gern mal ein paar Code-Schnipsel bekommen

 

Dann bastel mal hier mit.

 

MT4:

#import "meine.dll" 
  void an_dll(string send); 
#import

//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
 {
  string strSend;
  strSend = Symbol()+";"+Bid+";"+Ask+";"+TimeToStr(TimeCurrent(), TIME_DATE|TIME_SECONDS); 
  an_dll(strSend);
  return(0);
 }
//+------------------------------------------------------------------+

 

Delphi (ich hoffe, es passt auch für FreePascal)

uses
 ...

type
 Tbytes = array [0..200] of byte;

procedure an_dll(cc : Tbytes); stdcall;
var strText : String;
   ii : integer;
begin
 strText := '';
 for ii := 0 to 200 do
 begin
   strText := strText + chr(cc[ii]);
   if cc[ii] = 00 then break;
 end;
   
 try
   MessageDlg(strText, mtWarning, [mbOK], 0);
 except on e : exception do
   begin
     MessageDlg(e.Message, mtError, [mbOK], 0);
   end;
 end;
end;

exports
 an_dll; 
begin
;
end.

 

Das wäre ein Beispiel für call by value mit statischer Speicherreservierung für die Übergabe und simpler Umsetzung. Ist übrigens auch ein schönes Beispiel, wie Exploits entstehen können (Übergabe von mehr als 200 Byte und dadurch Überschreiben des Speichers mit Malware-Code).

Link to comment
Share on other sites

Dann bastel mal hier mit.

 

Das wäre ein Beispiel für call by value mit statischer Speicherreservierung für die Übergabe und simpler Umsetzung. Ist übrigens auch ein schönes Beispiel, wie Exploits entstehen können (Übergabe von mehr als 200 Byte und dadurch Überschreiben des Speichers mit Malware-Code).

 

Danke RAiNWORM für den Code! :nyam1:

 

wenn mal alles auf Anhieb klappen würde - jetzt findet das :badtaste_:-Programm (Lazarus) den Identifier <MessageDlg> nicht :head:

mache für heute Schluß - morgen ist auch noch ein Tag fürs "blöd" werden

Edited by mtbf40
Link to comment
Share on other sites

wenn mal alles auf Anhieb klappen würde - jetzt findet das :badtaste_:-Programm (Lazarus) den Identifier nicht :head:

In Delphi müsste man dazu die Unit Dialogs in die uses oben aufnehmen. Die Funktion sollte einfach den übergebenen String in einer Messagebox ausgeben. Kannst du nach Belieben ersetzen.

Link to comment
Share on other sites

Dann bastel mal hier mit.

 

MT4:

#import "meine.dll" 
  void an_dll(string cc); //<----- 1. Änderung statt send <-> cc
#import

//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
 {
  string strSend;
  strSend = Symbol()+";"+Bid+";"+Ask+";"+TimeToStr(TimeCurrent(), TIME_DATE|TIME_SECONDS); 
  an_dll(strSend);
  return(0);
 }
//+------------------------------------------------------------------+

 

Delphi (ich hoffe, es passt auch für FreePascal)

uses
 ...

type
 Tbytes = array [0..200] of byte;

procedure an_dll(cc : Tbytes); stdcall;
var strText : String;
   ii : integer;
begin
 strText := '';
 for ii := 0 to 200 do
 begin
   strText := strText + chr(cc[ii]);
   if cc[ii] = 00 then break;
 end;
   
 try
   MessageDlg(strText, mtWarning, [mbOK], 0);
 except on e : exception do
   begin
     MessageDlg(e.Message, mtError, [mbOK], 0);
   end;
 end;
end;

exports
 an_dll; 
begin
;
end.

 

Das wäre ein Beispiel für call by value mit statischer Speicherreservierung für die Übergabe und simpler Umsetzung. Ist übrigens auch ein schönes Beispiel, wie Exploits entstehen können (Übergabe von mehr als 200 Byte und dadurch Überschreiben des Speichers mit Malware-Code).

 

so!!! habe jetzt alles zum laufen bekommen :palomitas: - dll kompiliert mt4-Skript erstellt und PENG Error in MT4

 

function 'an_dll' call from dll 'meine.dll' critical error - bekommst Du auch diesen Fehler??

 

habe im mt4-Skript eine Änderung gemacht: siehe oben - Variable send mit cc ersetzt - muss nicht der gleiche Name für die Variable im mt4-Skript und in der dll existieren?

Link to comment
Share on other sites

update: die dll hat es sich anders überlegt und produziert nun keinen Fehler mehr!! warum auch immer...

 

ABER: es popt kein Message-Dialog auf :plorar1:... bin weiter am ausprobieren :schimpf:

 

 

Setze mal nur zum Test in deine GUI ein.

 

var
 buttonSelected : Integer;
begin
 // Show a custom dialog
 buttonSelected := MessageDlg('Custom dialog',mtCustom, 
                             [mbYes,mbAll,mbCancel], 0);

 // Show the button type selected
 if buttonSelected = mrYes    then ShowMessage('Yes pressed');
 if buttonSelected = mrAll    then ShowMessage('All pressed');
 if buttonSelected = mrCancel then ShowMessage('Cancel pressed');
end;

Link to comment
Share on other sites

die Messages funktionieren - was ich jetzt festgestellt habe ist, das mt4-Skript ruft die Funktion aus der DLL überhaupt nicht auf - ich :burn:

 

//#include <common_functions.mqh>

#import "meine.dll" 
  void an_dll(string cc);
#import

//+------------------------------------------------------------------+
//| expert start function                                        	|
//+------------------------------------------------------------------+
int start()
 {
  string strSend;
  strSend = Symbol()+";"+Bid+";"+Ask+";"+TimeToStr(TimeCurrent(), TIME_DATE|TIME_SECONDS); 
  //log("StrSend_"+strSend);
  return(0);
 }

 

dazu habe ich die Bestätigung eingeschaltet das ich DLL-Aufrufe betätigen muß - und da kommt nix mit "klick mal ok" :argg:

 

entweder steckt da der Teufel dahinter oder PH!!

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
×
×
  • Create New...