文章 "摆脱自制的 DLL" - 页 3

 
Dmitri Custurov #:
我想知道是否有可能获得指向函数的真正指针。使用 typedef 获得的指针在 mql 程序中运行得非常好。但不幸的是,我没能把它们传入 dll。

如果你了解 C++ + 内置汇编程序,知道向堆栈中放入什么以及如何放入,并且清楚远调用和近调用的术语,那么你可以试试。我不能保证一定能成功,但这是可能的。

 
哪里出错了?
#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)); // Crash.

  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

各处的长度应为 4 或更少

复制超过 2GB 的文件可以正常工作

获取数组的起始地址:

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

您代码中的示例与此截然不同。我试图从地址中获取值。

文章中有一个示例。

我已经强调了按地址写入的地方。但是,文章中的这个示例也会导致崩溃。

当然会......原型是从 4(32 位地址,类似无符号 int)开始的,而你编译/运行的是 5(64)。

你不能相信任何人,如果使用 WinAPI,请自己编写原型。或者最好编写自己的 DLL,让它调用 winapi,楼上的 mql 提供更高级别的接口。

 
Aliaksandr Hryshyn #:

复制超过 2GB 可以正常工作

获取数组的初始地址

我忽略了 64 位地址这一点。但使用更正后的地址时还是会崩溃。这真的可行吗?我能看看修正后的 fxsaber 代码的完整示例吗?

到目前为止,我仍然认为 WinAPI 的地址与 MQL 不兼容。

 
Aliaksandr Hryshyn #:

修好了你的:

Maxim Kuznetsov#:

当然可以......原型来自 4(32 位地址,如无符号 int),在 5(64)中编译/运行。

谢谢,现在可以了。
#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)); // Crash.

  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