C ++ Access violation writing at 0x00000000 in dll in mql4
Firstly, I am new to C ++ (almost a week later), so forgive me if this is obvious. Also, I have hunted many posts with similar problems. Either my understanding is simply underdeveloped, or none of them have relevant information to help me understand this problem.
In Metatrader 4, I am trying to figure out how to pass a structured variable to a dll and change the variables stored in the said structure. So far, I have had great success even with structures. Then I ran into a problem.
I've narrowed it down to using strings. If so, please take a look at the following code I used to focus on solving this problem and help me understand why I keep getting the "Write access error at 0x00000000" error whenever I try to run the script in mt4 ...
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;
}
source to share
From mql4 documentation: http://docs.mql4.com/basis/preprosessor/import
You cannot use the following parameters for imported functions:
- pointers (*);
- references to objects containing dynamic arrays and / or pointers.
Classes, string arrays or complex objects containing strings and / or dynamic arrays of any type cannot be passed as a parameter to a function imported from a DLL.
The imported function takes a pointer and apparently is not supported by mql4.
You should probably use a fixed size character array to pass data to and from dlls:
as:
struct Naming {
char m_name[255];
}
The function should accept a reference to this structure (but this is probably not supported) or accept the structure directly and return the structure.
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;
}
The call will look like this:
name = NameTest(name);
source to share
I know this is a little weird, but I am answering my own question because I figured out what was going on ... at least at least.
So here's the deal. Technically speaking, you can pass a structure that contains a string. What you cannot do is edit the line. The structure does not automatically convert a string to char []. So when the dll tries to edit the string, it causes an access violation because the string is not actually a string in C ++, but a char array disguised as a string.
However, I figured out how to pass the structure containing the string and change the value in the dll. This is how I did it.
--- Starting from the mql4 code --- First, I declared a structure with char [] instead of a string.
struct Naming
{
char word[65];
} name;
Then I initialized char [] with a null value, checked it, passed the structure and checked if the value was set correctly.
ArrayInitialize(name.word, '\0');
Print("original name: ", CharArrayToString(name.word));
if( NameTest( name ) )
{
Print("new name: ", CharArrayToString(name.word));
}
--- now the C ++ code --- I have declared the same structure.
struct Naming
{
char n_name[65];
};
Then the function. I first had to write the string literal in a temporary char []. I looped through the for loop to allocate the elements to char [] in the structure. The problem is that char [] from struct is not a constant, but char temp []. I got around this by taking each char into a char variable and then storing that variable value in a char [] structure.
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;
}
This code works nicely.
source to share