3

首先,我是 C++ 新手(近一周),如果这很明显,请原谅我。另外,我搜索了许多具有类似问题的帖子。要么我的理解不够深入,要么没有相关信息可以帮助我理解这个问题。

在 Metatrader 4 中,我试图弄清楚如何将结构变量传递给 dll,并修改存储在所述结构中的变量。到目前为止,我已经取得了巨大的成功,即使在处理结构数组时也是如此。然后我遇到了一个问题。

我已将问题缩小到使用字符串。如果您愿意,请查看以下代码,我曾用它来专注于解决此问题,并帮助我理解为什么每当我尝试在 mt4 中运行脚本时,我都会不断收到此“访问冲突写入 0x00000000”错误.

mql4 代码:

struct Naming
{
  string word;
} name;

#import  "SampleDLLtest.dll"
bool     NameTest(Naming &name);
#import

int init() { return(0); }

int start()
{
   Print("original name: ", name.word);
   if( NameTest( name ) )
   {
     Print("new name: ", name.word);
   }

   //---
   return(0);
}

这是相关的dll代码:

#define WIN32_LEAN_AND_MEAN
#include "stdafx.h"
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <string>

BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
   //---
   switch (ul_reason_for_call)
   {
      case DLL_PROCESS_ATTACH:
      case DLL_THREAD_ATTACH:
      case DLL_THREAD_DETACH:
      case DLL_PROCESS_DETACH:
      break;
   }

   //---
   return(TRUE);
}

struct Naming
{
   std::string n_name;
};

bool __stdcall NameTest(Naming *name)
{
   name->n_name = "Captain Success";

   return true;
}
4

2 回答 2

2

来自 mql4 的文档:http: //docs.mql4.com/basis/preprosessor/import

以下不能用于导入函数中的参数:

  • 指针(*);
  • 链接到包含动态数组和/或指针的对象。

不能将包含任何类型的字符串和/或动态数组的类、字符串数组或复杂对象作为参数传递给从 DLL 导入的函数。

导入的函数需要一个指针,mql4 显然不支持。

您可能应该使用固定大小的字符数组将数据传入和传出 dll:

像:

struct Naming {
  char m_name[255];
}

该函数需要接受对该结构的引用(但这可能也不支持)或直接接受该结构并返回该结构。

Naming NameTest(Naming name) {

  strncpy(name.m_name, "New Content", sizeof(name.m_name) -1);
  if (sizeof(name.m_name) > 0) {
      name.m_name[sizeof(name)-1] = 0;
  }
  return name;
}

调用它看起来像这样:

name = NameTest(name);
于 2015-06-09T08:48:52.263 回答
1

我知道这有点奇怪,但我正在回答我自己的问题,因为我知道发生了什么......至少至少。

所以这里是交易。从技术上讲,您可以传递一个包含字符串的结构。你不能做的是编辑字符串。结构中没有将字符串自动转换为 char[]。因此,当 dll 尝试编辑字符串时,它会引发访问冲突,因为字符串在 C++ 中并不是真正的字符串,而是伪装成字符串的 char 数组。

也就是说,我确实解决了如何传递包含字符串的结构,并修改 dll 中的值。这是我的做法。

---从 mql4 代码开始--- 首先,我用 char[] 而不是字符串来声明结构。

struct Naming
{
  char word[65];
} name;

然后我用空值初始化 char[],检查它,传递结构,并检查值是否设置正确。

ArrayInitialize(name.word, '\0');
Print("original name: ", CharArrayToString(name.word));
if( NameTest( name ) )
{
   Print("new name: ", CharArrayToString(name.word));
}

---现在到 C++ 代码---我声明了相同的结构。

struct Naming
{
    char n_name[65];
};

然后是函数。我首先必须在临时 char[] 中捕获字符串文字。我循环了一个 for 循环来将元素分配给结构中的 char[]。问题是,结构中的 char[] 不是 const,而 char temp[] 是。我通过将每个 char 捕获到一个 char 变量中来解决这个问题,然后将该变量值存储在 struct char[] 中。

bool __stdcall NameTest(Naming *name)
{
    char temp[] = "Captain Success";

    for (int i = 0; temp[i] != '\0'; i++)
    {
        char t = temp[i];
        name->n_name[i] = t;
    }

    return true;
}

这段代码工作得很好。

于 2015-06-09T21:29:50.670 回答