Metatrader 4 Unresolved import function call

 

Hi, I am trying to import a dynamic library coded in C++ in my EA.

Only problem is that despite the functions being exported, my EA does not load them properly.

The C++ code is as follows:

CONSOLEAPPLICATION2_API bool AsciiToUnicode(const char * szAscii, wchar_t * szUnicode)
CONSOLEAPPLICATION2_API bool UnicodeToAscii(const wchar_t * szUnicode, char * szAscii)

And the Import function call is as follows:


#import "Analytical.dll"
bool UnicodeToAscii(const string szUnicode, char szAscii);
#import

The resulting error is:

2016.11.02 15:00:55.316 Dulcimer AUDUSD,M1: unresolved import function call
2016.11.02 15:00:55.316 Cannot find 'UnicodeToAscii' in 'Analytical.dll'
2016.11.02 15:00:55.316 Dulcimer AUDUSD,M1: 89.18343333262493
2016.11.02 14:47:57.288 Dulcimer AUDUSD,M1: initialized
2016.11.02 14:47:50.241 Expert Dulcimer AUDUSD,M1: loaded successfully

Please help with a fix.

 
Lewis Mbuthia: Only problem is that despite the functions being exported, my EA does not load them properly.
Your import says the second parameter is a single char not an array of char's.
 
Lewis Mbuthia:

Hi, I am trying to import a dynamic library coded in C++ in my EA.

Only problem is that despite the functions being exported, my EA does not load them properly.

The C++ code is as follows:

CONSOLEAPPLICATION2_API bool AsciiToUnicode(const char * szAscii, wchar_t * szUnicode)
CONSOLEAPPLICATION2_API bool UnicodeToAscii(const wchar_t * szUnicode, char * szAscii)

And the Import function call is as follows:


#import "Analytical.dll"
bool UnicodeToAscii(const string szUnicode, char szAscii);
#import

The resulting error is:

2016.11.02 15:00:55.316 Dulcimer AUDUSD,M1: unresolved import function call
2016.11.02 15:00:55.316 Cannot find 'UnicodeToAscii' in 'Analytical.dll'
2016.11.02 15:00:55.316 Dulcimer AUDUSD,M1: 89.18343333262493
2016.11.02 14:47:57.288 Dulcimer AUDUSD,M1: initialized
2016.11.02 14:47:50.241 Expert Dulcimer AUDUSD,M1: loaded successfully

Please help with a fix.

 

 

 

 For now you can't send string to dll, only char array.

#import "Analytical.dll"
bool UnicodeToAscii(char &a0[], char szAscii);
#import
...
char a[];
StringToCharArray(szUnicode,a);
UnicodeToAscii(a, ...);
 
whroeder1:
Your import says the second parameter is a single char not an array of char's.

Thanks. I have recoded the dll and now I'm getting this error...

Access violation read to 0x00004868

Any ideas?

 
Lewis Mbuthia:

Thanks. I have recoded the dll and now I'm getting this error...

Access violation read to 0x00004868

Any ideas?

Firstly, MQL4 has native functions for the conversions which you are trying to do. A string datatype in MQL4 is always a Unicode string. An Ascii string has to be represented as a uchar[] array. You can convert between these using StringToCharArray and CharArrayToString. For example:

// Unicode string...
string
strExample = "My input string";
  
// Convert to an Ascii string, which has to be held as uchar[]
uchar arrAscii[];
StringToCharArray(strExample, arrAscii, 0, StringLen(strExample));
  
// Convert from Ascii back to native Unicode string
string strRoundTrip = CharArrayToString(arrAscii);

The one point to note is that you can use StringToCharArray(strExample, arrAscii) instead of StringToCharArray(strExample, arrAscii, 0StringLen(strExample)) but the former will add a terminating null character at the end of the array. In the above example the size of arrAscii would then be 16 characters/bytes, not 15.

The following is therefore pointless in itself, because MQL4 provides all this natively, but it does illustrate how to pass Unicode and Ascii strings in and out of a DLL... 

A Unicode string can be passed to a DLL as a const input parameter just by defining the type in the DLL import as "string". But, to pass an in/out buffer, which the DLL writes into, the Unicode buffer must be declared as ushort[]. An Ascii string must be passed in or out of a DLL as uchar[].

For example, take the following 4 DLL functions which do the combinations of Unicode <--> Ascii: 

/* No checks on buffer size in the following - for basic example purposes only. Unicode <--> Ascii conversion does not 
necessarily use N bytes/characters for Ascii and 2N bytes for Unicode as assumed here. */


extern "C" __declspec(dllexport) int CopyUnicodeToUnicode(const wchar_t * InputString, wchar_t * OutputBuffer)
{
        wcscpy(OutputBuffer, InputString);
        return wcslen(OutputBuffer);
}

extern "C" __declspec(dllexport) int CopyAsciiToAscii(const char * InputString, char * OutputBuffer)
{
        strcpy(OutputBuffer, InputString);
        return strlen(OutputBuffer);
}

extern "C" __declspec(dllexport) int CopyUnicodeToAscii(const wchar_t * InputString, char * OutputBuffer)
{
        int len = wcslen(InputString);
        WideCharToMultiByte(CP_UTF8, 0, InputString, len, OutputBuffer, len, NULL, NULL);
        return len;
}

extern "C" __declspec(dllexport) int CopyAsciiToUnicode(const char * InputString, wchar_t * OutputBuffer)
{
        int len = strlen(InputString);
        MultiByteToWideChar(CP_UTF8, 0, InputString, len, OutputBuffer, len);
        return len;
}

These functions can be imported in MQL4 as follows:

#import "MyDll.dll"
   int CopyUnicodeToUnicode(string, ushort&[]);
   int CopyAsciiToAscii(uchar&[], uchar&[]);
   int CopyUnicodeToAscii(string, uchar&[]);
   int CopyAsciiToUnicode(uchar&[], ushort&[]);
#import

The two functions which take Unicode input parameters can have those parameters declared as string. The two functions which take Unicode output buffers must have those buffers defined as ushort[], not as string.

The functions can then be used in MQL4 as follows:

void OnStart()
{
   Print(Test_UnicodeToUnicode("Hello"));
   Print(Test_AsciiToAscii("Hello"));
   Print(Test_UnicodeToAscii("Hello"));
   Print(Test_AsciiToUnicode("Hello"));
}

string Test_UnicodeToUnicode(string InputString)
{
   // The Unicode output buffer must be declared as ushort[],
   // with the array large enough to receive the output
   ushort arrDest[];
   ArrayResize(arrDest, StringLen(InputString));
  
   int len = CopyUnicodeToUnicode(InputString, arrDest);
  
   // Convert the ushort[] output to a native MQL4 Unicode string
   return ShortArrayToString(arrDest, 0, len);
}

string Test_AsciiToAscii(string InputString)
{
   // The Ascii input must be created by converting the MQL4 Unicode string
   // to a uchar[] array of Ascii bytes/characters
   uchar arrInput[];
   StringToCharArray(InputString, arrInput, 0, StringLen(InputString));

   // The Ascii output must be received by declaring a uchar[] array,
   // large enough to receive the output
   uchar arrDest[];
   ArrayResize(arrDest, StringLen(InputString));
  
   int len = CopyAsciiToAscii(arrInput, arrDest);
  
   // Convert the uchar[] Ascii output back to a native MQL4 Unicode string
   return CharArrayToString(arrDest, 0, len);
}

string Test_UnicodeToAscii(string InputString)
{
   // The Ascii output must be received by declaring a uchar[] array,
   // large enough to receive the output
   uchar arrDest[];
   ArrayResize(arrDest, StringLen(InputString));
  
   int len = CopyUnicodeToAscii(InputString, arrDest);
  
   // Convert the uchar[] Ascii output back to a native MQL4 Unicode string
   return CharArrayToString(arrDest, 0, len);
}

string Test_AsciiToUnicode(string InputString)
{
   // The Ascii input must be created by converting the MQL4 Unicode string
   // to a uchar[] array of Ascii bytes/characters
   uchar arrInput[];
   StringToCharArray(InputString, arrInput, 0, StringLen(InputString));

   // The Unicode output buffer must be declared as ushort[],
   // with the array large enough to receive the output
   ushort arrDest[];
   ArrayResize(arrDest, StringLen(InputString));
  
   int len = CopyAsciiToUnicode(arrInput, arrDest);
  
   // Convert the ushort[] output to a native MQL4 Unicode string
   return ShortArrayToString(arrDest, 0, len);
}
Reason: