wspoldzielenie pamieci

O jezykach programowania w platformach i nie tylko.
mlody87
Gaduła
Gaduła
Posty: 192
Rejestracja: 14 cze 2012, 13:19

wspoldzielenie pamieci

Nieprzeczytany post autor: mlody87 »

Hej!
Mam wydawaloby sie banalny problem ale nie moge sobie z nim poradzic.

Kod: Zaznacz cały

#define INVALID_HANDLE_VALUE 	-1
#define BUF_SIZE 				512
#define PAGE_READWRITE			0x0004
#define FILE_MAP_ALL_ACCESS		0xf001F
#define FILE_MAP_READ   		4

#import "kernel32.dll"
	int		CreateFileMappingA(int hFile, int lpAttributes, int flProtect, int dwMaximumSizeHigh, int dwMaximumSizeLow, string lpName);
	int 	MapViewOfFile(int hFileMappingObject, int dwDesiredAccess, int dwFileOffsetHigh, int dwFileOffsetLow, int dwNumberOfBytesToMap);
	int		UnmapViewOfFile(int	lpBaseAddress);
	int 	RtlMoveMemory(int DestPtr, string s, int Length);	
	int		CloseHandle(int hwnd);	
	
	int uchwyt;
	string buf;

Kod: Zaznacz cały

int uchwyt;
uchwyt=CreateFileMappingA(INVALID_HANDLE_VALUE,0,PAGE_READWRITE,0,BUF_SIZE,"test");
 if(uchwyt==NULL) { MessageBox("nie dziala"); }
tworze sobie obszar w pamieci.

Kod: Zaznacz cały

    buf = MapViewOfFile(uchwyt, FILE_MAP_ALL_ACCESS, 0, 0, BUF_SIZE); 
if(buf==" ") { MessageBox("PYUSTY"); } else { MessageBox(buf); }
UnmapViewOfFile(buf);
no i odczytuje. Problem w tym, ze za kazdym razem zawartosc jest inna. Sa to zmieniajace sie liczby. Czy ten obszar pamieci nie powinien byc pusty?

Jakiej funkcji uzyc zeby cos do niego zapisac?
pozdrawiam!:)
Obrazek

dulf
Pasjonat
Pasjonat
Posty: 399
Rejestracja: 24 kwie 2010, 15:13

Re: wspoldzielenie pamieci

Nieprzeczytany post autor: dulf »

Tak się nie da .Obszar dzielony musisz mieć zarządzany przez .dll .
Odnosisz się do niego jak do ciągu bajtów , od interpretacji w kodzie zależy jak go wykorzystasz.
Funkcje mapujące zwracają wskaźnik do jego początku i nie bardzo jest to do wyłuskania w mql .
W dll robisz funkcje które mają do niego dostęp i za pomocą tych fun zapisujesz i czytasz .
Nie znam pascala w C++ przykładowa biblioteka (w załączniku .dll) :

Kod: Zaznacz cały

#include <windows.h>
//---------------------------------------------------------------------------
extern "C"
{
  bool __declspec(dllexport)    __stdcall Init(LPCSTR name);
  void __declspec(dllexport)    __stdcall Deinit(void);
  bool __declspec(dllexport)    __stdcall WriteStrBuff(const char* s);
  LPCSTR __declspec(dllexport)  __stdcall ReadStrBuff(void);
}

//--------------------------------------------------------------------------
PBYTE pBuff = 0 ;
HANDLE hFileMapp = 0;
const int SizeBuff = 1024 ;
const char*ret0 ="" ;
//--------------------------------------------------------------------------
#pragma argsused
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
        return 1;
}
//---------------------------------------------------------------------------
//----------------------------------------------------------------------------
HANDLE QCreateFileMapping(LPCSTR name)
{
  HANDLE h ;

    h = CreateFileMapping(INVALID_HANDLE_VALUE,NULL,PAGE_READWRITE,
                            0,SizeBuff,name);
         return h ;
}
//---------------------------------------------------------------------------
PBYTE QMapViewOfFile(HANDLE hFileMapping)
{
    return (PBYTE)MapViewOfFile(hFileMapping,FILE_MAP_READ|FILE_MAP_WRITE,
                   0,0,0);
}
//----------------------------------------------------------------------------
void __stdcall Deinit(void)
{
    if(pBuff)
    {
      UnmapViewOfFile(pBuff);
      pBuff = NULL ;
    }
    if(hFileMapp)
    {
     CloseHandle(hFileMapp);
     hFileMapp = NULL;
    }

}

//---------------------------------------------------------------------------
bool __stdcall Init(LPCSTR name)
{
        hFileMapp = QCreateFileMapping(name);

    if(NULL!=hFileMapp)
    {
        pBuff = QMapViewOfFile(hFileMapp);

        if(pBuff!=NULL)
        {
           memset(pBuff,0,SizeBuff);
           return true ;
        }
      return false ;
    }
           return false ;
}
//---------------------------------------------------------------------------
bool __stdcall WriteStrBuff(const char* s)
{
  if(pBuff!=NULL)
  {
    lstrcpy(pBuff,s);
    return true;
  }
    return false;
}
//---------------------------------------------------------------------------
LPCSTR __stdcall ReadStrBuff(void)
{
  if(pBuff!=NULL)
  {
   if(pBuff[0]!= 0)
   {
      return pBuff ;
   }
  }
      return ret0 ;
}
EA Piszące do wspólnego obszaru :

Kod: Zaznacz cały

#import "filemapp.dll"
  bool Init(string);
  void Deinit();
  bool WriteStrBuff(string);
  string ReadStrBuff();
#import

//+------------------------------------------------------------------+
int init()
  {
//----
       bool ret =   Init("filemem");

       if(false == ret)
       {
            MessageBox("Error Init()");
       }
//----
   return(0);
  }
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
int deinit()
  {
//----
    Deinit();
//----
   return(0);
  }
//+------------------------------------------------------------------+
int counter = 0 ;
//+------------------------------------------------------------------+
int start()
  {
//----    
          counter++ ;
          WriteStrBuff("Ala ma kota = " + counter );


//----
   return(0);
  }
//+------------------------------------------------------------------+
EA Czytające z niego :

Kod: Zaznacz cały

#import "filemapp.dll"
  bool Init(string);
  void Deinit();
  bool WriteStrBuff(string);
  string ReadStrBuff();
#import


//+------------------------------------------------------------------+
int init()
  {
//----
       bool ret =   Init("filemem");

       if(false == ret)
       {
            MessageBox("Error Init()");
       }
//----
   return(0);
  }
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
int deinit()
  {
//----
    Deinit();
//----
   return(0);
  }
//+------------------------------------------------------------------+
string read ;
//+------------------------------------------------------------------+
int start()
  {
//----    
          
          read = ReadStrBuff();
          Comment(read);

//----
   return(0);
  }
Najlepiej każde EA uruchomić na dwóch oddzielnych platformach ,bo mogą być kłopoty z inicjalizacją .
Niby działa i na jednej dla EA na oddzielnych wykresach ,ale tylko jako eksperyment można to potraktować.
Przy więcej niż jednym EA na danej platformie z tą samą biblioteką trzeba separować zmienne globalne w .dll bo sie poebie dane .
Zaznaczam że to tylko rozwiązanie demonstracyjne.
Nie masz wymaganych uprawnień, aby zobaczyć pliki załączone do tego posta.
Nie spiesz się , zawsze zdążysz stracić .

mlody87
Gaduła
Gaduła
Posty: 192
Rejestracja: 14 cze 2012, 13:19

Re: wspoldzielenie pamieci

Nieprzeczytany post autor: mlody87 »

Dziala!:) Wielkie dzieki! :) Uprosci mi to znacznie sprawe:)
Mozesz jeszcze napisac dlaczego tak bardzo zaznaczasz ze to bardziej kod 'pogladowy'?
Obrazek

dulf
Pasjonat
Pasjonat
Posty: 399
Rejestracja: 24 kwie 2010, 15:13

Re: wspoldzielenie pamieci

Nieprzeczytany post autor: dulf »

Dlatego że przy załadowaniu tej .dll na jednym wykresie nie ma problemu .
Jeśli jednak będziesz ją chciał wykorzystać na kilku wykresach to ten kod jest zbyt prymitywny.
Dll jest ładowany jednokrotnie bez względu na ilość EA załadowanych na wykresy ,ale każdy wykres tworzy oddzielny dla siebie wątek i dane globalne traktuje jako swoje własne w tym przypadku będzie to np. wskaźnik do bufora który jest modyfikowany (pamięć z nim związana).Kolejne wątki ("wykresy") z EA będą więc wzajemnie nadpisywać sobie dane globalne.
Najłatwiej umieścić zmienne w sekcji TLS biblioteki , czyli oznaczyć je jako lokalne dla wątku lub tak napisać bibliotekę żeby nie doszło do nadpisywania pamięci .
http://pl.wikipedia.org/wiki/Pami%C4%99 ... w%C4%85tku
Mi proste opcje kompilatora nie działają dobrze i tak skompilowana dll nie działa,ma prawo.Osobiście używam innego rozwiązania związanego z klasami C++ ,więc nie chce mi sie wnikać co jest skopane .
Można TLS za pomocą APIWin zakodzić ,ale to jest temat dla masochistów.
A właściwie to pewnie chodzi o XP:
Na systemach Windows starszych niż Vista oraz Server 2008 __declspec(thread) działa w bibliotekach DLL tylko gdy są one powiązane statycznie z plikiem wykonywalnym i nie zadziała z bibliotekami ładowanymi przez LoadLibrary() (może wystąpić błąd ochrony lub uszkodzenia danych).
Są również dodatkowe zasady: "Zasady i ograniczenia TLS" (j. ang) w MSDN.
-- Dodano: pt 31-05-2013, 5:04 --

W ten sam sposób można wymieniać dane innego typu np. podzielić bufor na dane dla string i tablicy double.
W załaczniku .dll - modyfikacja funkcji Init + funkcje dla tablicy double :

Kod: Zaznacz cały

#include <windows.h>
//---------------------------------------------------------------------------
extern "C"
{
  bool __declspec(dllexport)    __stdcall Init(LPCSTR name,int len_str,int len_dbl);
  void __declspec(dllexport)    __stdcall Deinit(void);
  bool __declspec(dllexport)    __stdcall WriteStrBuff(const char* s);
  LPCSTR __declspec(dllexport)  __stdcall ReadStrBuff(void);
  bool   __declspec(dllexport)  __stdcall WriteDblBuff(double d[],int len);
  bool   __declspec(dllexport)  __stdcall ReadDblBuff(double*d,int len);
}

//--------------------------------------------------------------------------
PBYTE  pBuff = 0 ;
HANDLE  hFileMapp = 0;
int  SizeBuff ;
int  OffsetDbl ;
const char* ret0 ="" ;

//--------------------------------------------------------------------------
#pragma argsused
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
        return 1;
}
//---------------------------------------------------------------------------
//----------------------------------------------------------------------------
HANDLE QCreateFileMapping(LPCSTR name)
{
  HANDLE h ;

    h = CreateFileMapping(INVALID_HANDLE_VALUE,NULL,PAGE_READWRITE,
                            0,SizeBuff,name);
         return h ;
}
//---------------------------------------------------------------------------
PBYTE QMapViewOfFile(HANDLE hFileMapping)
{
    return (PBYTE)MapViewOfFile(hFileMapping,FILE_MAP_READ|FILE_MAP_WRITE,
                   0,0,0);
}
//----------------------------------------------------------------------------
void __stdcall Deinit(void)
{
    if(pBuff)
    {
      UnmapViewOfFile(pBuff);
      pBuff = NULL ;
    }
    if(hFileMapp)
    {
     CloseHandle(hFileMapp);
     hFileMapp = NULL;
    }

}

//---------------------------------------------------------------------------
bool __stdcall Init(LPCSTR name,int len_str,int len_dbl)
{
        SizeBuff = len_str+ (len_dbl*sizeof(double));
        OffsetDbl = len_str ;

        hFileMapp = QCreateFileMapping(name);

    if(NULL!=hFileMapp)
    {
        pBuff = QMapViewOfFile(hFileMapp);

        if(pBuff!=NULL)
        {
           memset(pBuff,0,SizeBuff);
           return true ;
        }
      return false ;
    }
           return false ;
}
//---------------------------------------------------------------------------
bool __stdcall WriteStrBuff(const char* s)
{
  if(pBuff!=NULL)
  {
    lstrcpy(pBuff,s);
    return true;
  }
    return false;
}
//---------------------------------------------------------------------------
LPCSTR __stdcall ReadStrBuff(void)
{
  if(pBuff!=NULL)
  {
   if(pBuff[0]!= 0)
   {
      return pBuff ;
   }
  }
      return ret0 ;
}
//---------------------------------------------------------------------------
bool __stdcall WriteDblBuff(double d[],int len)
{
  if(pBuff!=NULL)
  {
    memcpy((pBuff+OffsetDbl),d,len*sizeof(double));
    return true;
  }
    return false;
}
//---------------------------------------------------------------------------
bool __stdcall ReadDblBuff(double*d,int len)
{
  if(pBuff!=NULL)
  {
    memcpy(d,(pBuff+OffsetDbl),len*sizeof(double));
    return true;
  }
    return false;
}
//---------------------------------------------------------------------------
EA Pisze :

Kod: Zaznacz cały

#import "filemapp.dll"
  bool Init(string,int len_str,int len_dbl);
  void Deinit();
  bool WriteStrBuff(string);
  string ReadStrBuff();
  bool WriteDblBuff(double d[],int len);
  bool ReadDblBuff(double d[],int len);
#import

#define LEN_STR 512
#define LEN_DBL 1024

double Dbl_Buff[LEN_DBL]; 

//+------------------------------------------------------------------+
int init()
  {
//----
       bool ret =   Init("filemem",LEN_STR,LEN_DBL);

       if(false == ret)
       {
            MessageBox("Error Init()");
       }
//----
   return(0);
  }
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
int deinit()
  {
//----
    Deinit();
//----
   return(0);
  }
//+------------------------------------------------------------------+
int counter = 0 ;
//+------------------------------------------------------------------+
int start()
  {
//----    
          Dbl_Buff[0] = Close[0] ;                      // pierwsza pozycja w tablicy
          Dbl_Buff[LEN_DBL-1] = MathAbs((Close[0]-Open[0])/Point) ; // ostatnia pozycja w tablicy
          
          counter++ ;
          WriteStrBuff("Ala ma kota ->"+counter);
          //zapis tablicy
          WriteDblBuff(Dbl_Buff,LEN_DBL);


//----
   return(0);
  }
EA Czyta :

Kod: Zaznacz cały

#import "filemapp.dll"
  bool Init(string,int len_str,int len_dbl);
  void Deinit();
  bool WriteStrBuff(string);
  string ReadStrBuff();
  bool WriteDblBuff(double d[],int len);
  bool ReadDblBuff(double d[],int len);
#import

#define LEN_STR 512
#define LEN_DBL 1024

double Dbl_Buff[LEN_DBL]; 

//+------------------------------------------------------------------+
int init()
  {
//----
       bool ret =   Init("filemem",LEN_STR,LEN_DBL);

       if(false == ret)
       {
            MessageBox("Error Init()");
       }
//----
   return(0);
  }
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
int deinit()
  {
//----
    Deinit();
//----
   return(0);
  }
//+------------------------------------------------------------------+
string read ;
//+------------------------------------------------------------------+
int start()
  {
//----    
          
          read = ReadStrBuff();
          ReadDblBuff(Dbl_Buff,LEN_DBL);
          read = read +" Close Candle[0] = " + DoubleToStr(Dbl_Buff[0],Digits)+ " Size Candle = " + 
          DoubleToStr(Dbl_Buff[LEN_DBL-1],0);
          Comment(read);

//----
   return(0);
  }
RATUNKU !!!!!!

-- Dodano: pt 31-05-2013, 5:06 --

NIe mogę edytować postu ,zle wstawiłem znaczniki .
Nie masz wymaganych uprawnień, aby zobaczyć pliki załączone do tego posta.
Nie spiesz się , zawsze zdążysz stracić .

mlody87
Gaduła
Gaduła
Posty: 192
Rejestracja: 14 cze 2012, 13:19

Re: wspoldzielenie pamieci

Nieprzeczytany post autor: mlody87 »

Dzieki wielkie!:) A mozna np utworzyc dwa obszary pamieci o roznych nazwach i odwolywac sie do nich w czasie jednego ticku?
Obrazek

dulf
Pasjonat
Pasjonat
Posty: 399
Rejestracja: 24 kwie 2010, 15:13

Re: wspoldzielenie pamieci

Nieprzeczytany post autor: dulf »

Tutaj nie bo jest tylko jeden wskażnik i jedno mapowanie w dll .Nie bardzo to ma sens tworzyc kolejny nazwany przydział bo odwołanie i tak będzie szeregowo w mql ,czyli pierwszy i kolejny .Tak samo można dopisać funkcję która czyta i pisze np. fragmenty przydzielonej pamięci ,tak jak zwykłej tablicy i w ten sposób operować.
W tym przykładzie masz podzielony bufor na fragment 512 bajtów przeznaczony na string i fragment 1024 size-double *bajt .
Mozna napisać funkcję która będzie się poruszała dowolnie po wspólnej pamięci ,a co gdzie zapiszesz i odczytasz można podać jako parametr funkcji - offset.Trzeba tylko pamiętać o rozmiarach zmiennych.
Nie spiesz się , zawsze zdążysz stracić .

mlody87
Gaduła
Gaduła
Posty: 192
Rejestracja: 14 cze 2012, 13:19

Re: wspoldzielenie pamieci

Nieprzeczytany post autor: mlody87 »

Ok dzieki:) Dziala, jednak mam pewien problem. Probouje obsluzyc ta dllke zewnetrznym programem zeby wysylal jakies dane do strategii za pomoca tablicy (stringi leca normlanie bez errorow). Co dziwne, dane te sa zapisywane do pamieci i odczytywane przez strategie jednak na koncu pokazuje sie error jak w zalaczniku. Wiesz moze co moze go powodowac kiedy wszystko dziala jak nalezy? ;)
Prawdopodobnie cos z rozmiarami tablicy ale nie moge tego ogarnac.
Nie masz wymaganych uprawnień, aby zobaczyć pliki załączone do tego posta.
Obrazek

dulf
Pasjonat
Pasjonat
Posty: 399
Rejestracja: 24 kwie 2010, 15:13

Re: wspoldzielenie pamieci

Nieprzeczytany post autor: dulf »

Nie testowałem tego .dll z aplikacje zewnętrzną .Ten komunikat to pochodzi z MT4 czy z twojego programu[?] .
Jak w programie używasz tej .dll ? poksz kod .
Ogólnie to sprawdzę , musisz w swojej aplikacji zrobić tak:
Załadować dynamicznie .dll .
Pobrać adresy funkcji.
Wykonać funkcję Init z takimi samymi parametrami jak w MQL aby zainicjować dane w dll .
Spróbowac użyć fun z .dll .
Nie spiesz się , zawsze zdążysz stracić .

mlody87
Gaduła
Gaduła
Posty: 192
Rejestracja: 14 cze 2012, 13:19

Re: wspoldzielenie pamieci

Nieprzeczytany post autor: mlody87 »

Z zewnetrznej taki blad. Z tego co widzialem prgoramujesz w C, ja to napisalem w Delphi ale pewnie ogarniesz.

Kod: Zaznacz cały

 var //deklarujemy tablice
 Dbl_Buff:array of double;

//ladujemy funkcje z biblioteki
  function  Init(name:ShortString;len_str:integer;len_dbl:integer):boolean; stdcall; external 'filemapp.dll';
  procedure Deinit(); stdcall; external 'filemapp.dll';
  function WriteStrBuff(s:ShortString):boolean; stdcall; external 'filemapp.dll';
  function ReadStrBuff():ShortString; stdcall; external 'filemapp.dll';
  function WriteDblBuff(d:array of double;len:integer):boolean; stdcall; external 'filemapp.dll';
  function ReadDblBuff(d:array of double;len:integer):boolean; stdcall; external 'filemapp.dll';
No i wywoluje teraz na OnClik Buttona:

Kod: Zaznacz cały

//wyzej sie lacze
if(zlecenie=false) then begin ShowMessage('Error Init()'); end;

//ustawiamy wielkosc tablicy  
SetLength(Dbl_Buff,LEN_DBL);

Dbl_Buff[0] := 123;                      // pierwsza pozycja w tablicy
          WriteStrBuff('Ala ma kota');
          WriteDblBuff(Dbl_Buff,LEN_DBL);

//rozlaczenie
No i ea w MT4 odczytuje mi 123 ale jednoczesnie w programi pojawia sie error.
Obrazek

dulf
Pasjonat
Pasjonat
Posty: 399
Rejestracja: 24 kwie 2010, 15:13

Re: wspoldzielenie pamieci

Nieprzeczytany post autor: dulf »

Init masz wywołane raz ? Narazie klece App.Powinno być jednokrotnie np w OnCreate App albo konstruktorze zaraz po pomyślnym załadowaniu .dll i pobraniu adrr fun .
Nie spiesz się , zawsze zdążysz stracić .

ODPOWIEDZ