How to pass and return double array to a DLL function?

Questions about MultiCharts and user contributed studies.
jek
Posts: 166
Joined: 24 Dec 2006
Has thanked: 1 time
Been thanked: 2 times

How to pass and return double array to a DLL function?

Postby jek » 02 Oct 2008

I've been trying to figure out the simplest way to pass an array of doubles and return an array of doubles to a user DLL function. It can be the same array.

Simplicity is the most important thing.

It used to be possible to do something like this with the old EasyLanguage DLL kit, I believe.

I can get the following to compile in TS but not in MC.

Any suggestions?

Also note that variable type declarations appear to be rejected by MC.

Code: Select all

{
external: "mydll.dll", int, "arrayExampleAddOne", (double*) {Values}, long {startAddress}, long {arraySize} ;
external: "mydll.dll", int, "arrayExampleAddOne", double* {Values}, long {startAddress}, long {arraySize} ;
}
definedllfunc: "mydll.dll", int, "arrayExampleAddOne", multiple;

Input: notUsed(0);

{
Var: long dwStartAddr(0), long dwArraySize(0), i(0), int Result(0);
}
Var: dwStartAddr(0), dwArraySize(0), Count(0), Result(0);

Array: double inOutArray[5](0.0);

Once Begin
  For Count = 0 to dwArraySize Begin
    inOutArray[Count] = Count;
  End;
End;
  dwStartAddr = ArrayStartAddr(inOutArray);
  dwArraySize = ArraySize(inOutArray);

Result = arrayExampleAddOne((double)&inOutArray[0], (long) dwStartAddr, (long) dwArraySize );

Plot1(inOutArray[0], "TestArray0");
Plot2(inOutArray[1], "TestArray1");
Plot3(inOutArray[2], "TestArray2");
Plot4(inOutArray[3], "TestArray3");

User avatar
Marina Pashkova
Posts: 2758
Joined: 27 Jul 2007

Postby Marina Pashkova » 10 Oct 2008

Hi jek,

PowerLanguage does not support multiple as the reserved word. The parameters must be listed one after the other, the way they appear in the dll function. Please see the sample code below:



Code: Select all

definedllfunc: "mydll.dll", int, "arrayExampleAddOne", lpdouble , long , long ;

Input: notUsed(0);

Var: dwStartAddr(0), dwArraySize(0), Count(0), Result(0);

Array: double inOutArray[5](0.0);

Once Begin
 For Count = 0 to dwArraySize Begin
   inOutArray[Count] = Count;
 End;
End;
 dwStartAddr = ArrayStartAddr(inOutArray);
 dwArraySize = ArraySize(inOutArray);

Result = arrayExampleAddOne((double)&inOutArray[0], (long) dwStartAddr, (long) dwArraySize );

Plot1(inOutArray[0], "TestArray0");
Plot2(inOutArray[1], "TestArray1");
Plot3(inOutArray[2], "TestArray2");
Plot4(inOutArray[3], "TestArray3");

jek
Posts: 166
Joined: 24 Dec 2006
Has thanked: 1 time
Been thanked: 2 times

Postby jek » 16 Oct 2008

Thank you.

This looks as though the pointer to the array is passed in to the function.

Does this mean that you can get by in this simple case without using ArrayStartAddr() and ArraySize()?

In other words, if I pass in the inOutArray pointer, can I just reference it in C with inOutArray[0] to access the value?

jek
Posts: 166
Joined: 24 Dec 2006
Has thanked: 1 time
Been thanked: 2 times

Postby jek » 28 Oct 2008

It sure would be nice to have a simple example of just passing an array of doubles and returning an array of doubles.

Does this mean that you can get by in this simple case without using ArrayStartAddr() and ArraySize()?

In other words, if I pass in the inOutArray pointer, can I just reference it in C wiUth inOutArray[0] to access the value?


I got around to trying this. It seems that the inOutArray pointer properly passes in the value by reference and returns the value by reference. But only the first value. In C this is inOutArray[0].

If I try to use or set inOutArray[1], then it doesn't work. Aren't the values stored near each other? I found that FindAddress_Array() didn't seem to do the right thing - the return value didn't point to the valid data but inOutArray did.

Code: Select all

external: "...\file.dll", int, "arrayExampleAddOne", lpdouble {Values}, long {startAddress}, long {arraySize} ;

Var: dwStartAddr(0), dwArraySize(4), Count(0), Result(0);

Array: double inOutArray[5];

Once Begin
  For Count = 0 to dwArraySize Begin
    inOutArray[Count] = 1 + Count;
  End;
End;

Result = arrayExampleAddOne((double)&inOutArray[0], (long) dwStartAddr, (long) dwArraySize );

Plot1(inOutArray[0], "TestArray0");
Plot2(inOutArray[1], "TestArray1");
Plot3(inOutArray[2], "TestArray2");
Plot4(inOutArray[3], "TestArray3");

jek
Posts: 166
Joined: 24 Dec 2006
Has thanked: 1 time
Been thanked: 2 times

Simple example to return a double array from a DLL.

Postby jek » 11 Nov 2008

Would you please provide an example of the simplest case of passing an array of doubles to and from a DLL function?

Thanks!

jek
Posts: 166
Joined: 24 Dec 2006
Has thanked: 1 time
Been thanked: 2 times

Postby jek » 14 Nov 2008

Any user out there have a simple example with arrays?

jek
Posts: 166
Joined: 24 Dec 2006
Has thanked: 1 time
Been thanked: 2 times

Postby jek » 14 Nov 2008

The ArraySize() doesn't seem to work.

Try the following code that always prints 0 for the array size.

Code: Select all

Inputs:
unused("hello");


Array: double inOutArray[20](0.0);
Vars:
  int   Count(0),
  int   numReturned(0),
  int   firstDebug(7),
        dwStartAddr(0),
        dwArraySize(0)
  ;

  For Count = 0 to 19 Begin
    inOutArray[Count] = Count;
  End;


dwStartAddr = ArrayStartAddr(inOutArray);
dwArraySize = ArraySize(inOutArray);
print(dwStartAddr, " ", dwArraySize);


Does MC believe that the elkit32 array functions work?
I'm using build 1724.

For reference, the following links seem to be the best descriptions of the old array code:
https://www.TS.com/Discussion ... c_ID=19846
https://www.TS.com/Discussion ... c_ID=29258

jek
Posts: 166
Joined: 24 Dec 2006
Has thanked: 1 time
Been thanked: 2 times

Postby jek » 28 Nov 2008

Now that you have had a chance to return from TraderExpo, could you please confirm that this is or isn't a bug?

Thanks!

User avatar
Marina Pashkova
Posts: 2758
Joined: 27 Jul 2007

Postby Marina Pashkova » 04 Dec 2008

Hi jek,

The behavior you are describing is not a bug. It is just a matter of realization. To pass an array into a dll you don't need to use ArraySize at all. It is enough to use ArrayStartAddr()

If you do need to get array size as well, the function that you need is array_getmaxindex. For example:

once dwArraySize = array_getmaxindex(inoutarray);

I hope the above answers your questions.

Best regards.

User avatar
Marina Pashkova
Posts: 2758
Joined: 27 Jul 2007

Postby Marina Pashkova » 04 Dec 2008

And yes, elkit32 array functions work in MultiCharts.

jek
Posts: 166
Joined: 24 Dec 2006
Has thanked: 1 time
Been thanked: 2 times

Postby jek » 17 Dec 2008

I'm reporting back for the benefit of others.

I was unable to get the legacy array mechanism to work. It would send values from MC to the DLL but it wouldn't see the modified values. I won't say that I exhaustively tried everything possible, but I tried a lot.

I bit the bullet and installed VC to be able to use the #import required for using IEasyLanguageObject. It sure would be nice if gcc could be used with IEasyLanguage.

I did get that to work, though it was not possible to use DLLs compiled using TS 8.4 build 1683 tskit.dll. The DLLs had to be compiled using MC PLKit.dll. The resulting DLLs worked with both MC and TS.

Presumably this is because TS 1683 has a newer object interface and MC 4 has an older object interface and TS is backward compatible.

That is all for now.


Return to “MultiCharts”