Search code examples
c++dllmql4

C++ Access violation write to 0x00000000 in dll in mql4


First, I am new to C++ (nearly a week into it), so forgive me if this is obvious. Also, I have hunted through many posts with similar issues. Either my understanding is just not developed enough, or none had relevant info to help me understand this issue.

In Metatrader 4, I am trying to figure out how to pass a structure variable to a dll, and modify variables stored in said structure. So far, I have had great success, even when dealing with structure arrays. Then I encountered an issue.

I have narrowed the problem down to the use of strings. If you will, please have a look at the following code, which I have used to focus on solving this problem, and help me understand why I keep getting this 'Access violation write to 0x00000000' error whenever I try and run the script in mt4.

The mql4 code:

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);
}

This is the relevant dll code:

#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;
}

Solution

  • From the documentation of mql4: http://docs.mql4.com/basis/preprosessor/import

    The following can't be used for parameters in imported functions:

    • pointers (*);
    • links to objects that contain dynamic arrays and/or pointers.

    Classes, string arrays or complex objects that contain strings and/or dynamic arrays of any types cannot be passed as a parameter to functions imported from DLL.

    The imported function takes a pointer and that is apparently not supported by mql4.

    You should probably use a fixed size array of characters to pass data to and from the dll:

    like:

    struct Naming {
      char m_name[255];
    }
    

    The function would need to accept a reference to this struct (but this is probably not supported either) or accept the struct directly and return the struct.

    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;
    }
    

    Calling it would then look like this:

    name = NameTest(name);