Kütüphaneler: DLL olmadan Dosya Eşleme - sayfa 11

 
o_o:

buna kaydı kapatmak denmez, dosyayı kapatmak ve silmek denir.

Bu yüzden

artık var olmayan bir şeyi açmaya çalışıyorsunuz.

Kütüphane koduna baktığımda, dosyanın yalnızca CMemMapFile sınıfının Close() işlevi doğrudan çağrıldığında değil, aynı zamanda bu sınıfın nesnesinin işaretçisi silindiğinde de silindiğini gördüm, çünkü bu işlev sınıf yıkıcısında çağrılıyor. Biraz kafam karıştı. Bir dosyayı yazma ve okuma farklı çağrı bağlamlarında (kapsamlarında) kullanılıyorsa, sınıf nesneleri oluşturmanın dinamik yönteminin kullanılamayacağı ortaya çıktı. Örneğin, terminalin bir çizelgesi bir dosyaya veri yazıyor, ikincisi verileri okuyor ve bu dosyayı siliyor. Dosyanın zorla silinmemesi için nesne değişkeninin her zaman global seviyede tutulması gerektiği ortaya çıkmaktadır. Okunan verinin boyutunu belirtmeden yapmanın mümkün olup olmadığı da açık değildir. Yani, yazarken verinin boyutunu biliyoruz, ancak başka bir grafikte okurken, örneğin dize değerleri durumunda olduğu gibi, verinin boyutunu önceden bilemeyebiliriz. Muhtemelen ya ben bir şeyi yanlış anladım ya da kütüphanede değiştirilmesi gereken başka bir şey var.

Benim hatam. İşaretçi kullanmadan ve dolayısıyla delete kullanmadan tekrar kontrol ettim. Bu durumda, kapsamdan çıkarken (bir fonksiyondan), sınıf nesnesinin yerel değişkeni, destructor'a açık bir çağrı yapılmadan yok edilir.

Alıcı tarafında alınan verinin boyutu ile ilgili hala bir soru var.

 
fxsaber:

Kütüphane için yazara teşekkürler!

Herhangi bir veriyi aktarmak için fonksiyonlar yaptım. Aşağıdaki kod, kene örneği üzerindeki çalışmalarını göstermektedir


Sonuç


Süper! Sizin kodunuza benzeterek kütüphanenin kullanımını kendim için basitleştirdim.

 
MT4 için fiyat transferi örneği

Ticaret, otomatik ticaret sistemleri ve ticaret stratejilerinin test edilmesi üzerine forum

Metatrader 4 için NamedPipes

fxsaber, 2017.11.30 14:18

Exchange_Data.mqh

#include <MemMapLib.mqh>
#include <TypeToBytes.mqh>

template <typename T>
class EXCHANGE_DATA
{
private:
  CMemMapFile* FileMemory;

public:  
  // Veriler için belirtilen uzunlukta bellek ayırır 
  EXCHANGE_DATA( const int Amount, const bool ModeCreate = false, string FileName = "Local\\test" )
  {
// FileName += _Symbol;
    
    this.FileMemory = new CMemMapFile;
      
    if (this.FileMemory.Open(FileName, sizeof(T) * Amount + sizeof(int) + HEAD_MEM, ModeCreate ? modeCreate : modeOpen) != 0)
    {
      Alert("FileMemory.Open - ERROR!");
      
      delete &this;
    }
  }
  
  ~EXCHANGE_DATA( void )
  {
    this.FileMemory.Close();
    
    delete this.FileMemory;
  }

  // Verileri belleğe yazar
  void DataSave( const T &Data[], const bool FromBegin = true  ) const
  {
    const int Size = ::ArraySize(Data) * sizeof(T);
    uchar Bytes[];
    
    _ArrayCopy(Bytes, _R(Size).Bytes);              // Miktar kaydedildi 
    _ArrayCopy(Bytes, _R(Data).Bytes, sizeof(int)); // Veriler kaydedildi
  
        if (FromBegin)
          this.FileMemory.Seek(0, SEEK_SET);
  
        this.FileMemory.Write(Bytes, ::ArraySize(Bytes)); // Her şeyi belleğe boşalttı
    
    return;
  }
  
  // Bellekten veri okur
  int DataLoad( T &Data[], const bool FromBegin = true ) const
  {
        if (FromBegin)
          this.FileMemory.Seek(0, SEEK_SET);
  
        uchar Bytes[];
          
        this.FileMemory.Read(Bytes, sizeof(int));  // Bellekten veri miktarını okuyun 
        this.FileMemory.Read(Bytes, _R(Bytes)[0]); // Verinin kendisini aldım
  
        _ArrayCopy(Data, Bytes);              // Verileri bir diziye döktü
    
    return(::ArraySize(Data));
  }  
};


PriceGiver.mq4

#property strict

#include "Exchange_Data.mqh"

#define  AMOUNT 100

EXCHANGE_DATA<MqlTick> ExchangeTicks(AMOUNT, true);

const bool Init = EventSetMillisecondTimer(100);

void OnTimer( void )
{
  static MqlTick Ticks[1];
  
  if (SymbolInfoTick(_Symbol, Ticks[0]))
    ExchangeTicks.DataSave(Ticks);
}


PriceTaker.mq4

#property strict

#include "Exchange_Data.mqh"

#define  AMOUNT 100

EXCHANGE_DATA<MqlTick> ExchangeTicks(AMOUNT);

const bool Init = EventSetMillisecondTimer(100);

#define  TOSTRING(A) (#A + " = " + (string)(A) + " ")

void OnTimer( void )
{  
  static MqlTick PrevTick = {0};  
  MqlTick Ticks[];
  
  if ((ExchangeTicks.DataLoad(Ticks) > 0) &&
      ((Ticks[0].bid != PrevTick.bid) || (Ticks[0].ask != PrevTick.ask)))
  {
    Print(TOSTRING(Ticks[0].time) + TOSTRING(Ticks[0].bid) + TOSTRING(Ticks[0].ask));
    
    PrevTick = Ticks[0];
  }
}


PriceGiver.ex4 ve PriceTaker.ex4 dosyalarını çalıştırın.


Sonuç

2017.11.30 15:13:55.101 Expert PriceGiver EURUSD,M1: removed
2017.11.30 15:13:55.091 PriceGiver EURUSD,M1: uninit reason 1
2017.11.30 15:13:51.006 Expert PriceTaker GBPAUD,M1: removed
2017.11.30 15:13:50.996 PriceTaker GBPAUD,M1: uninit reason 1
2017.11.30 15:13:49.168 PriceTaker GBPAUD,M1: Ticks[0].time = 2017.11.30 15:13:41 Ticks[0].bid = 1.18483 Ticks[0].ask = 1.18487 
2017.11.30 15:13:48.838 PriceTaker GBPAUD,M1: Ticks[0].time = 2017.11.30 15:13:41 Ticks[0].bid = 1.18484 Ticks[0].ask = 1.18489 
2017.11.30 15:13:48.186 PriceTaker GBPAUD,M1: Ticks[0].time = 2017.11.30 15:13:40 Ticks[0].bid = 1.18483 Ticks[0].ask = 1.18487 
2017.11.30 15:13:47.751 PriceTaker GBPAUD,M1: Ticks[0].time = 2017.11.30 15:13:40 Ticks[0].bid = 1.18484 Ticks[0].ask = 1.18488 
2017.11.30 15:13:42.178 PriceTaker GBPAUD,M1: Ticks[0].time = 2017.11.30 15:13:34 Ticks[0].bid = 1.18485 Ticks[0].ask = 1.18489 
2017.11.30 15:13:41.633 PriceTaker GBPAUD,M1: Ticks[0].time = 2017.11.30 15:13:34 Ticks[0].bid = 1.18484 Ticks[0].ask = 1.18488 
2017.11.30 15:13:37.588 PriceTaker GBPAUD,M1: Ticks[0].time = 2017.11.30 15:13:30 Ticks[0].bid = 1.18483 Ticks[0].ask = 1.18487 
2017.11.30 15:13:36.175 PriceTaker GBPAUD,M1: Ticks[0].time = 2017.11.30 15:13:28 Ticks[0].bid = 1.18481 Ticks[0].ask = 1.18485 
2017.11.30 15:13:30.717 PriceTaker GBPAUD,M1: Ticks[0].time = 2017.11.30 15:13:23 Ticks[0].bid = 1.18482 Ticks[0].ask = 1.18486 
2017.11.30 15:13:29.514 PriceTaker GBPAUD,M1: Ticks[0].time = 2017.11.30 15:13:22 Ticks[0].bid = 1.18483 Ticks[0].ask = 1.18487 
2017.11.30 15:13:27.324 PriceTaker GBPAUD,M1: Ticks[0].time = 2017.11.30 15:13:19 Ticks[0].bid = 1.1848 Ticks[0].ask = 1.18484 
2017.11.30 15:13:26.994 PriceTaker GBPAUD,M1: Ticks[0].time = 2017.11.30 15:13:19 Ticks[0].bid = 1.18482 Ticks[0].ask = 1.18486 
2017.11.30 15:13:26.012 PriceTaker GBPAUD,M1: Ticks[0].time = 2017.11.30 15:13:18 Ticks[0].bid = 1.18481 Ticks[0].ask = 1.18485 
2017.11.30 15:13:25.584 PriceTaker GBPAUD,M1: Ticks[0].time = 2017.11.30 15:13:18 Ticks[0].bid = 1.18482 Ticks[0].ask = 1.18486 
2017.11.30 15:13:25.254 PriceTaker GBPAUD,M1: Ticks[0].time = 2017.11.30 15:13:16 Ticks[0].bid = 1.18481 Ticks[0].ask = 1.18485 
2017.11.30 15:13:25.147 PriceTaker GBPAUD,M1: initialized
2017.11.30 15:13:24.049 Expert Sparring\PriceTaker GBPAUD,M1: loaded successfully
2017.11.30 15:13:21.157 PriceGiver EURUSD,M1: initialized
2017.11.30 15:13:19.617 Expert Sparring\PriceGiver EURUSD,M1: loaded successfully
 

Kütüphanenin CMemMapFile::Open yönteminde küçük bir hata vardır. Dosya tanıtıcısını (HANDLE64 tipi) döndürmesi gerekir, ancak bunun yerine 0 veya bir hata kodu döndürür.

Buna ek olarak, CMemMapApi::Write ve CMemMapApi::Read okuma ve yazma yöntemleri bir nedenden dolayı verileri iki kez kopyalar (ve baytlar arasında döngü yapılır!) ve ek olarak, yalnızca belirli bir parça gerekli olmasına rağmen dosyanın tamamının üzerine yazılır/okunur.

Genel olarak, normal görünmelerini sağladım, gereksiz şeyler yorumlandı :

//------------------------------------------------------------------ Write
int CMemMapApi::Write(HANDLE64 hmem, const uchar &buf[], DWORD pos, int sz, DWORD &err) // belirtilen sayıda baytı belleğe yazar
{
  if (hmem==NULL) return(-1);
  PBYTE64 view=ViewFile(hmem, err);  if (view==0 || err!=0) return(-1); // eğer açık değilse
  DWORD size=GetSize(hmem, err);  if (pos+sz>size) { UnViewFile(view);  return(-2); }; // boyut daha küçükse, çık
  /* 
 uchar src[]; ArrayResize(src, size); memcpyX(src, view, size); // bytebuffer aldı
 for(int i=0; i<sz; i++) src[pos+i+HEAD_MEM]=buf[i]; // belleğe yaz
 memcpyX(view, src, size); // geri kopyala
 */    
  memcpyX(view+HEAD_MEM+pos, buf, sz);  
  UnViewFile(view); // görünümü kapattı
  return(0); // Tamam olarak döndü.
}
//------------------------------------------------------------------ Read
int CMemMapApi::Read(HANDLE64 hmem, uchar &buf[], DWORD pos, int sz, DWORD &err) // bellekten belirtilen sayıda bayt okur
{
  if (hmem==NULL) return(-1);
  PBYTE64 view=ViewFile(hmem, err);  if (view==0 || err!=0) return(-1); // eğer açık değilse
  DWORD size=GetSize(hmem, err); // boyutu aldım
  /* 
 uchar src[]; ArrayResize(src, size); memcpyX(src, view, size); // bytebuffer aldı
 ArrayResize(buf, sz);
 int i=0; for(i=0; i<sz && pos+i<size; i++) buf[i]=src[pos+i+HEAD_MEM]; // read bytes
 */    
  sz= fmin(sz, size-pos);
  ArrayResize(buf, sz);
  memcpyX(buf, view+HEAD_MEM+pos, sz);
  UnViewFile(view); // görünümü kapattı
  return sz; // kopyalanan bayt sayısı
}
İlk fonksiyonun derlenebilmesi için, memcpyX ve memcpy fonksiyonlarında diziler için const ayarını yapmanız gerekir ki yazar bunu yapma zahmetine girmemiştir.
 

dwMaximumSizeHigh içinde sıfır geçilmesi nedeniyle büyük boyutlar kopyalanırken hata oluştu

        if (mode==modeCreate) 
           hmem=CreateFileMappingWX(INVALID_HANDLE_VALUE64, NULL, PAGE_READWRITE, 0, size + HEAD_MEM, path); // bir bellek nesnesi oluşturun

Bu şekilde düzeltildi:

if (mode==modeCreate) 
           hmem=CreateFileMappingWX(INVALID_HANDLE_VALUE64, NULL, PAGE_READWRITE, size + HEAD_MEM, size + HEAD_MEM, path); // bir bellek nesnesi oluşturun


Bu boyut - 6 mb, sorunsuz aktarılır:

void OnStart()
{
   int bars = Bars(_Symbol, _Period);
   MqlRates rates[]; 
   ArraySetAsSeries(rates, true); 
   CopyRates(NULL, 0, 0, bars, rates); 

   int size = ArraySize(rates) * sizeof(MqlRates);
   
   uchar data[];
   _ArrayCopy(data, rates);
   
   CMemMapFile *hmem = new CMemMapFile();
   hmem.Open("test", size, modeCreate);
   hmem.Write(data, size);
   hmem.Close(); 
   delete hmem;

   Print(size);
}


 
pushdib:

Bu şekilde düzeltildi:

8 baytlık boyutun en yüksek 4 baytını uygun şekilde oraya aktarın.

 

Tamam, şimdi C# programında tüm raitlere sahibiz ve LINQ kullanarak ihtiyacımız olan her şeyi analiz edebiliriz.

Ancak, terminal ve uygulama arasındaki komut mekanizmasının nasıl düzenleneceği sorusu var.

Terminalden: new candle, new raites - dosyayı al

Uygulamadan: hesaplama tamamlandı, sonucu al (grafik üzerinde çiz, bir anlaşma aç).


Terminal ve kod arasındaki etkileşimin bu tür bir uygulamasında deneyimi olan var mı?

 
pushdib:

Tamam, şimdi bir C# programında tüm raitlere sahibiz ve her şeyi mükemmel bir şekilde analiz etmek için LINQ'yu kullanabiliriz.

Ancak, terminal ve uygulama arasındaki komut mekanizmasının nasıl düzenleneceği sorusu vardır.

Terminalden: yeni mum, yeni fiyatlar - dosyayı alın

Uygulamadan: hesaplama tamamlandı, sonucu alın (grafiğe çizin, bir anlaşma açın).


Terminal ve kod arasında bu tür bir etkileşim uygulaması konusunda deneyimi olan var mı?

Hepsini pip aracılığıyla yaptım - saat gibi çalışıyor.
 
Bu tek kelimeyle harika, emekleriniz için teşekkürler! -)). Aynı zamanda ikili dosyalarla nasıl çalışılacağını da öğrenmek zorunda kaldım ama buna değdi.
 

Lütfen bu durumda ne yapacağınızı önerin.

1. Bellekte 100 baytlık yeni bir dosya açtım.

2. İçine 100 bayt yazdım.

3. Başka bir Uzman Danışman'da 100 bayt okudum. Her şey yolunda.

4. Şimdi aynı dosyaya 50 veya 200 bayt nasıl yazılır?