dll and array

 

Could someone please post a sample of passing an array to a dll and then proccesing it within the dll. I ubnderstand how to pass the dll, but I am confused about using the array within the dll.

Thanks.

 
USForexGuy:

Could someone please post a sample of passing an array to a dll and then proccesing it within the dll. I ubnderstand how to pass the dll, but I am confused about using the array within the dll.

There's been a discussion of DLLs in a separate topic, including a mention of the example DLL which is included in MT4's samples subdirectory. That example is fairly useless, but one of the things which it is good for is demonstrating how to pass arrays to the DLL, and then how to process them within the DLL.

 
USForexGuy wrote >>

Could someone please post a sample of passing an array to a dll and then proccesing it within the dll. I ubnderstand how to pass the dll, but I am confused about using the array within the dll.

Thanks.

Within the DLL, chances are you need to have the function expect a pointer, then dereference that pointer in order to access the actual value stored in memory at that location.

Example:

If your function expects "int **a", which is a pointer to an array of ints, you would need to dereference it like this inside to get the value of the 0'th element: (*a)[0]

**doing a simple a[0] would give you the memory address instead of the value stored at that address**

Pointers are a bit hard to understand in the beginning, especially for arrays. If you post an example, I can help you get going.

Jon

 
Archael wrote >>

Within the DLL, chances are you need to have the function expect a pointer, then dereference that pointer in order to access the actual value stored in memory at that location.

Example:

If your function expects "int **a", which is a pointer to an array of ints, you would need to dereference it like this inside to get the value of the 0'th element: (*a)[0]

**doing a simple a[0] would give you the memory address instead of the value stored at that address**

Pointers are a bit hard to understand in the beginning, especially for arrays. If you post an example, I can help you get going.

Jon

Thanks for the response. I'm going to googel pointers.

 
Archael:

Example:

If your function expects "int **a", which is a pointer to an array of ints [...]

Excuse me if I'm going mad this morning, but isn't "int **" a pointer to an array of int-pointers? Or is it just that I'm having a pointer-mental-block day?


For example:


int TestArray1(int * Array, int GetElem)

{

return *(Array + GetElem);

}


int TestArray2(int Array[], int GetElem)

{

return Array[GetElem];

}


int TestArrayOfPointers(int ** Array, int GetElem)

{

return (*Array)[GetElem];

}


void main()

{

// Normal array of ints, processed using two different syntax forms

int ExampleArray[] = {0,1,2,3,4,5};

printf("Using TestArray1, item 3 is: %i\n", TestArray1(ExampleArray, 3));

printf("Using TestArray2, item 3 is: %i\n", TestArray2(ExampleArray, 3));


// Build an array of _pointers_ to integers, and access it via (*Array)[Elem]

int * ExamplePointerArray[] = {&ExampleArray[0],&ExampleArray[1],&ExampleArray[2],&ExampleArray[3],&ExampleArray[4],&ExampleArray[5]};

printf("Using array of pointers, item 3 is: %i\n", TestArrayOfPointers(ExamplePointerArray, 3));

}

 

Pointers are extremely versatile. There's dozens of ways of doing something that will end up being the final result. It all depends on exactly what is passed to the function and how you want to play with that array.

In your TestArray1 function, it simply expects an address in memory that will contain an integer. Then access to the value would simply be with a asterisk prefix to the variable. Of course, you can ignore boundaries and go further than that single integer if what you really passed was an array -- only you would know that but it's not good programming practice.

In your TestArray2 function, it is the exact same thing as TestArray1. An array is an address in memory just like a pointer except that you generally access it with variable[element] instead of *(variable+element). It is also better used when the size of the arrays are totally static and will not change -- for example, hours_in_a_day[24] would always be 24 since that will never change.

In your TestArray3 function (which is the correct method of doing it), you are expecting a pointer to an array of int's in this case. A unary (**) prefix could also be used differently but I'm not going to go into that right now. In this function, the advantage is that if you are passing an address to an array of ints, you can actually modify the address to affect the variable outside the local scope. malloc() is a great example of this advantage -- being able to allocate dynamically inside a function even if the declaration was somewhere else since you can change the address at that address.

The TestArray3 function could be passed 2 things, both being correct but used differently. You could pass either:

1. an address to an array of ints (if declared "int *a", you could pass "&a" which is the address of that pointer)

2. a 2-dimensional array of ints (if declared "int **a", you could simplay pass "a" which is the address pointing to the pointer -- the variable itself and whatever you did to it up to that point)

This can easily get confusing, it's not even simple for me to explain even if in my head it's as clear as a sunny day. Just keep in mind that pointers are there to optimize speed and versatility. If you compare an array of 10 integers, that would be 10x4 bytes on a 32-bit machine, which is 40 bytes. You could still play with that array inside a function by passing a pointer to it but since the poitner is simply an address in memory, you have access to the same thing with only 4bytes passed to the function. Needless to say, when you start playing with much larger arrays, it is very advantageous to do it via pointers.

Hope this clears a few things,

Jon

 
Archael:

In your TestArray3 function (which is the correct method of doing it), you are expecting a pointer to an array of int's in this case.

Not as far as I can see. TestArray3 (actually, "TestArrayOfPointers") is receiving an array containing a list of pointers to integers - i.e. a pointer to a block of memory containing a series of pointers - rather than the integers themselves. It's TestArray1 and TestArray2 which get passed a plain array of ints (i.e. a pointer to the memory containing the ints). You'd use TestArray1/TestArray2 if passing an int array from MQL. TestArrayOfPointers is fundamentally different to TestArray1/TestArray2. It's not the "correct" option out of three identical alternatives.


For example, using the above TestArray1(), you'd do the following in MQL:


#import "ExampleDll.dll"

int TestArray1(int & Array[], int GetElem);

#import


int start()

{

int ExampleArray[] = {0,1,2,3,4,5};

MessageBox("Elem 3 is: " + TestArray1(ExampleArray, 3));

}



If you pass the same MQL int array to TestArrayOfPointers() then it crashes - because it's expecting the array to contain int* rather than int, and tries to dereference to invalid addresses.


Unless, of course, I'm still having a pointer-mental-block day now that it's late at night rather than early in the morning...

 

Lol! The thing is that you are correct in your usage but it's your understanding that is somewhat flawed. I remember I used to be in that same position a long time ago ;)

In your example just above, you are passing the address of the array. In this case, your DLL should be expecting int *a or int a[]. Both will work since both are an address to a block of int's.

What I believe is throwing you off is that MQL4 does it slightly differently than C. In C, if you were to pass the address of an array (&a if declared int a[10] or int *a and allocated afterwards), you would be sending the address of that pointer so the function would need to have int **a as its argument. In MQL4 however, you are sending a pointer to the block so TestArray1/2 would need to be used. TestArrayOfPointer could also be used but it wouldn't be safe since changing the address could result in a violation or unexpected behaviour.

To summarize, you were correct at first when saying TestArray1/2 should be used. I just hope I helped clarify the differences between the two languages. It showed me at the same time how MQL4 treats and sends arrays behind the scenes.

To the thread starter. If this confused you more than anything else, don't hesitate to post back for help. JJC and I will take care of you ;)

 
Archael:

In your example just above, you are passing the address of the array. In this case, your DLL should be expecting int *a or int a[]. Both will work since both are an address to a block of int's. [...]

What I believe is throwing you off is that MQL4 does it slightly differently than C.

I know that. I used an example suitable for MQL because this is an MQL forum. It's not that C does things "differently" to MQL, or vice versa. It's that C provides more and different options, of which MQL is a subset.


In C, if you were to pass the address of an array (&a if declared int a[10] or int *a and allocated afterwards), you would be sending the address of that pointer

Indeed. But this is an MQL forum. You cannot send the "address of that pointer" from MQL - as far as I know. You can only send the pointer to an array, rather than the address of the pointer to the array. I'm not sure of the purpose of your initial "(*a)[0]" example on an MQL forum. I'm not aware that it's usable from MQL.


Even in C, there are fairly limited cases where you'd want to send the address of an array pointer rather than the pointer itself. For example, the Win32 API almost exclusively uses the latter.


I remember I used to be in that same position a long time ago ;)

Have your 13 years of experience included special classes in being patronising?

 

fwiw, I've been following this thread with interest, however the medium of talk does not allow for unambiguous dialogue and wires can get crossed etc.

English allows for subjectivity - code of some sort is vastly less subjective, yes?

I'm decades rusty on C but my rendition below is just perhaps possible descriptive dialogue to express ones ideas.

Should I be wrong in my "//...", forgive me, as said, decades rusty and without locating my [once well used] K&R I most likely have it all wrong :O)

.

Nevertheless, in the interests of those readers such as myself that may be finding this thread daunting [yet very interesting/relevant], my request is that a more objective script is required to give full justice to such an important topic.

How about it guys?

eg:

int *ptr; //ptr to type int

int **ptr; //ptr to (ptr to type int)

int a[]; //array of type int

int *a[]; //ptr to array of type int

int **a[]; //ptr to (array of ptrs to type int)

.

Formals:

MQL_____________C

int a[]____________int a[]

...

and perhaps for Actuals: also...

.

heck, I do not know but something along the lines as above sure would help me and hopefully others too.

.

Am looking forwards to some education!

Regards

 
fbj:

[...] and wires can get crossed etc.

Very true. I think Archael and I are indeed talking at cross purposes.


Am looking forwards to some education!

Probably best left to a specialist C/C++ forum. I can't imagine when you'd need to do "int **a[]" in anything which was actually related to MQL itself.

Reason: