Download MetaTrader 5
To add comments, please log in or register
Do you have Linux? Find out how to install MetaTrader on it!
Mike Brady
65
Mike Brady 2009.08.22 15:21 

Hi,


This question, or variants on the theme, seem to keep coming up but I can't find a comprehensive (or correct?) answer.


I've looked through the example in the experts\samples directory, but it doesn't really address my specific question. I can see an array of strings being sorted, but I can't see any example where the string value itself is set by the DLL.


What I want to do is define a function in my DLL that when called, will return 4 string values. Preferably, I'd like these to be in a structure but I can't see any evidence that MQL4 supports user-defined structures...(perhaps I'm wrong and someone can point out how this is done).


What I've tried so far is the following.


In my MQL4
----------
string orderDets[4]={ "XXXXXXXXXXXXXXXXXXXXXX",
                      "yyyyyyyyyyyyyyyyyyyyyy",
                      "zzzzzzzzzzzzzzzzzzzzzz",
                      "aaaaaaaaaaaaaaaaaaaaaa" };

int rc = TD_GetStringDetails(Symbol(), orderDets);


In my dll.mqh file
------------------
int TD_GetStringDetails(string, string& []);


In my dll
---------
int MT4_EXPFUNC __stdcall TD_GetStringDetails(char *sCurrency, char **orderDetails) {
....
}


This gives the following error...

2009.08.22 22:52:05 TradeDirector NZDUSD,H1: cannot call function 'TD_GetStringDetails' from dll 'TradeDirector.dll' (error 127)


Any suggestions on how I might be able to update the contents of the 4 strings in the orderDets array would be most appreciated.

JC
1389
JC 2009.08.27 15:48  
mjbrady:

This question, or variants on the theme, seem to keep coming up but I can't find a comprehensive (or correct?) answer.

I've looked through the example in the experts\samples directory, but it doesn't really address my specific question. I can see an array of strings being sorted, but I can't see any example where the string value itself is set by the DLL.

The following isn't necessarily "correct", but it does seem to work. The critical things are (a) the array dimensions must be initialised before passing the array to the DLL, and (b) arrays of strings get passed to a DLL as MqlStr*, not as char**.


This code takes a string array with (at least) two slots in it, and stores a new string in each one. It allocates a block of memory to hold each string, on the assumption that MT4 eventually tries to free the memory associated with strings. (If the array you pass in already contains values, then there will probably be a minor memory leak because the strings get replaced without ever being released.)


struct MqlStr {
	int	len;
	char    *string;
};


int __stdcall MyFunction(MqlStr * stringarray)
{
	const char * value1 = "Now is the winter of ";
	const char * value2 = "our discontent";

	int szString1 = lstrlenA(value1);
	char * string1 = (char*)malloc(szString1 + 1);
	lstrcpyA(string1, value1);

	int szString2 = lstrlenA(value2);
	char * string2 = (char*)malloc(szString2 + 1);
	lstrcpyA(string2, value2);

	stringarray[0].string = string1;
	stringarray[0].len = szString1;

	stringarray[1].string = string2;
	stringarray[1].len = szString2;

	return 0;
}
Mike Brady
65
Mike Brady 2009.08.27 22:25  
jjc:

The following isn't necessarily "correct", but it does seem to work. The critical things are (a) the array dimensions must be initialised before passing the array to the DLL, and (b) arrays of strings get passed to a DLL as MqlStr*, not as char**.


This code takes a string array with (at least) two slots in it, and stores a new string in each one. It allocates a block of memory to hold each string, on the assumption that MT4 eventually tries to free the memory associated with strings. (If the array you pass in already contains values, then there will probably be a minor memory leak because the strings get replaced without ever being released.)



Thanks for the tips jjc. I have managed to get this working cleanly, and w/o any leaks :-) by passing an array of strings by reference, and just making sure that each string is already initialised to a value which is at least the same size as the largest string value I wish to return from the DLL. In the DLL itself, the code is very similar to yours, except that it simply uses strcpy to overwrite the original string variable of MqlStr. Works like a charm.

Duncan McQueen
26
Duncan McQueen 2011.07.26 03:27  

I know this is an old topic - but can you post the code on how you did it? I am curious as to how to initialize the array prior to passing it to the dll and then what you refer to the variables as.


Thanks!

whroeder1
13593
whroeder1 2011.07.26 17:07  
bejglee
12
bejglee 2012.07.03 08:54  

I know this is an old topic, but is now current for me.

Solution of jcc doesn't work. I'm out of ideas :-(

I've tried this:

C++:

vector<string> array1;
array1.push_back("text 1");
array1.push_back("text 2");
array1.push_back("text 3");
...

static char* convert(const std::string &s)
{
   char* pc=new char[s.size()+1];
   std::strcpy(pc,s.c_str());
   return pc; 
}
...
MT4_EXPFUNC BOOL __stdcall getArray(MqlStr* arr)
{
        try
        {       for(int i=0;i<static_cast<int>(array1.size());i++)
                {       
                        const char* value=convert(array1[i]);

                        strcpy(arr[i].string,value);
                        arr[i].len=strlen(value);

                        delete[] value;
                }
        }
        catch (...){return(FALSE);}
        return(TRUE);
}

MQL4:

   #import "test.dll"
   bool getArray(string& array1[]);
   #import
   ...
   string array1[];
   if(getArray(array1))
   {
      if(ArraySize(array1)>0)
      {  
         for(int i=0;i<ArraySize(array1);i++)Print(array1[i]);
         ArrayResize(array1,0);
      }
   }
Jitendra Parmar
1093
Jitendra Parmar 2013.07.14 21:39  

again , I am trying the same thing in C# dll , and no success passing value from and to the dll , 

please any active user help  me in passing array of string ! 

 thanks in advance

Simon Gniadkowski
Moderator
17962
Simon Gniadkowski 2013.07.15 07:27  
hijeenu:

again , I am trying the same thing in C# dll , and no success passing value from and to the dll , 

please any active user help  me in passing array of string ! 

 thanks in advance


Please do not double post . . .  especially to old threads.
William Kreider
523
William Kreider 2014.06.16 19:18  
jjc:

The following isn't necessarily "correct", but it does seem to work. The critical things are (a) the array dimensions must be initialised before passing the array to the DLL, and (b) arrays of strings get passed to a DLL as MqlStr*, not as char**.


This code takes a string array with (at least) two slots in it, and stores a new string in each one. It allocates a block of memory to hold each string, on the assumption that MT4 eventually tries to free the memory associated with strings. (If the array you pass in already contains values, then there will probably be a minor memory leak because the strings get replaced without ever being released.)




any possible way we could see the Mql4 side of this scenario, thanks :) 

Hongliang Liu
1195
Hongliang Liu 2014.06.18 06:59  

i am writing some dll now,it seems that dll not support char very well,it use wchar_t instead.

i have an alternative solution: 

to return string array,another way is return wchar_t* in dll,which direct transfer to string in mql4

In dll:

__declspec(dllexport) wchar_t* Func(void) ;

 

 In mql4:

#import "xxx.dll" 

string Func(void); 

#import

 string strTemp =  Func();

 

you can construct the string with special separator in dll,such as "one;two;three",then split it in mql4 to get the string "one","two","three"

 

hope that be helpful 

/
To add comments, please log in or register