記事"自作 DLL の排除"についてのディスカッション - ページ 3

 
Dmitri Custurov #:
関数への本当のポインターを得ることは可能だろうか。typedefを使って取得したポインタは、mqlプログラム内では完璧に動作する。しかし残念なことに、私はそれをdllに渡すことに失敗した。

C++とビルトイン・アセンブラの知識があり、スタックに何をどのように置くか知っていて、far callとnear callという用語が明確であれば、試すことができる。うまくいくとは保証できないが、可能性はある。

 
どこが間違いなんだ?
#import "msvcrt.dll"
  int memcpy( const int &dst, const int src, const int cnt );
  int memcpy( const int &dst[], const int &src[], const int cnt );  
#import

void OnStart()
{
  int Array[];
  ArrayResize(Array, 1);
  Array[0] = 123;

  const int Address = msvcrt::memcpy(Array, Array, 0);
  int Value = 0;
  
  msvcrt::memcpy(Value, Address + 0, sizeof(int)); // クラッシュ。

  Print(Value);
}
 
fxsaber #:
どこが間違いなんだ?
#import "msvcrt.dll"
        int memcpy(int &dst, int &src[], int cnt);  
        int memcpy(int &dst[], int &src[], int cnt);  
#import



void OnStart() {
        int Array[];
        ArrayResize(Array, 1);
        Array[0] = 123;
        int Value = 0;
        
        msvcrt::memcpy(Value, Array, sizeof(int));
        Print(Value);   // 123
}
 
Edgar Akhmadeev #:

あなたのコードの例はまったく違います。私はアドレスから値を取得しようとしています。

記事の中に例があります。

#import "kernel32.dll"
  int OpenFileMappingW(int dwDesiredAccess, int bInheritHandle,  string lpName);
  int MapViewOfFile(int hFileMappingObject, int dwDesiredAccess, 
                      int dwFileOffsetHigh, int dwFileOffsetLow, int dwNumberOfBytesToMap);
  int UnmapViewOfFile(int lpBaseAddress);
  int CloseHandle(int hObject);
#import "msvcrt.dll"
  int memcpy(uchar &Destination[], int Source, int Length);
  int memcpy(int Destination, int &Source, int Length);
  int memcpy(int Destination, uchar &Source[], int Length);
#import

#define  FILE_MAP_ALL_ACCESS   0x000F001F

//+------------------------------------------------------------------+
//| スクリプト番組開始機能|
//+------------------------------------------------------------------+
void OnStart()
{
  //--- メモリ・オブジェクトを開く
  int hmem=OpenFileMappingW(FILE_MAP_ALL_ACCESS, 0, "Local\\file");
  //--- メモリポインタを取得する
  int view=MapViewOfFile(hmem, FILE_MAP_ALL_ACCESS, 0, 0, 0); 
  //--- メモリから最初の10バイトを読み込む
  uchar src[10];
  memcpy(src, view, 10);
  int num=10;
  //--- メモリの先頭に4バイトのint型数値を書き込む。
  memcpy(view, num, 4);
  //--- ビューを閉じる
  UnmapViewOfFile(view); 
  //--- オブジェクトを閉じる
  CloseHandle(hmem); 
}
アドレスで書かれているところを強調しました。しかし、この記事の例もクラッシュします。
 
fxsaber #:

あなたのコードの例はまったく違います。私はアドレスから値を取得しようとしています。

記事の中に例があります。

アドレスで書かれている箇所を強調しました。しかし、この記事の例もクラッシュを引き起こします。

あなたが何を望んでいるかはすぐに理解できました。確かにWinAPI関数から返されたアドレスはMQL5では使えません。しかし、アドレスは正しく引数に渡されます。

引数で受け取ったアドレスを表示し、それを返す簡単なDLLを書けば絶対確実です。そしてその結果をMQL5で比較してください。ここでは多くの人がC言語を実践している。

 
fxsaber #:
間違いはどこだ?
#import "msvcrt.dll"
ulong memcpy(ulong destination,ulong source,ulong count_bytes);
ulong memcpy(ulong destination,uchar &source[],ulong count_bytes);
ulong memcpy(ulong destination,ulong &source[],ulong count_bytes);
ulong memcpy(uchar &destination[],ulong source,ulong count_bytes);
ulong memcpy(ulong &destination[],ulong source,ulong count_bytes);
ulong memcpy(ulong &destination[],ulong source,ulong count_bytes);
#import

修正しました:

#import "msvcrt.dll"
  int memcpy(uchar &Destination[], int &Source, 
ulong Length);
  int memcpy(int &Destination, int &Source, ulong Length);
  int memcpy(int &Destination, uchar &Source[], ulong Length);
#import

どこでもLenghtは4以下であるべきです。

2GB以上のコピーはうまくいく

配列の開始アドレスの取得

uchar Source[];
ArrayResize(Source,1024*1024*1024);
ulong Source_pointer=memcpy(Source,0,0); 
 
fxsaber #:

あなたのコードの例はまったく違います。私はアドレスから値を取得しようとしています。

記事の中に例があります。

アドレスで書かれている箇所を強調しました。しかし、この記事の例もクラッシュを引き起こします。

プロトタイプは4(32ビットアドレス、unsigned int)のもので、コンパイルや実行は5(64ビット)で行います。

WinAPIを使うなら、誰も信用できない。もしくは、自分でDLLを書いて、winapiを引かせ、mqlの2階でより高いレベルのインターフェイスを与える方がいい。

 
Aliaksandr Hryshyn #:

2GB以上のコピー

配列の先頭アドレスを取得する

64ビットのアドレスで失敗しました。しかし、修正したアドレスでもクラッシュします。本当に動作するのでしょうか?修正したfxsaberコードの完全な例を見ることはできますか?

WinAPIのアドレスはMQLと互換性がありません。

 
Aliaksandr Hryshyn #:

あなたのは直した:

Maxim Kuznetsov#:

プロトタイプは 4 (32 bit address a la unsigned int) で、コンパイル/実行は 5 (64 bit) です。

ありがとう。
#import "msvcrt.dll"
  ulong memcpy( const int &dst, const ulong src, const int cnt );
  ulong memcpy( const int &dst[], const int &src[], const int cnt );  
#import

void OnStart()
{
  int Array[];
  ArrayResize(Array, 1);
  Array[0] = 123;

  const ulong Address = msvcrt::memcpy(Array, Array, 0);
  int Value = 0;
  
  msvcrt::memcpy(Value, Address + 0, sizeof(int)); // クラッシュ。

  Print(Value);
}
 
fxsaber #:
ありがとう。

最後のパラメータ(cnt)も64ビットです。size_t

https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/memcpy-wmemcpy

memcpy, wmemcpy
memcpy, wmemcpy
  • TylerMSFT
  • learn.microsoft.com
Learn more about: memcpy, wmemcpy