Bingo! - That did it!!!!
thank you Soooooooooooooooooooo much Florent, and Lance for your help.
This was no exercise (an exercise in frustration maybe) it is a crucial step in a project. This is the only way to find an Easy Language array element in memory so that I can acess it from a dll.
Thanks again.
------------------
Kind Regards
Mike
Announcement
Collapse
No announcement yet.
Accessing Array elements in Memory and converting a C++ Dll Declaration
Collapse
X
-
Mike
you should change the definition for ArrayFind_Address to
DECLARE FUNCTION FindAddress_Array LIB "C:\Program Files\Omega Research\Program\elkit32.dll" ALIAS "FindAddress_Array" _
(BYVAL lpArray AS DWORD, BYVAL ElemOffset AS LONG, BYVAL BarOffset AS LONG, BYVAL StartAddr AS DWORD, BYVAL ArraySize AS DWORD) AS DWORD
instead of BYREF lpArray AS DWORD.
Additionally there's not need to jump through hoops to return
a single from your FindArray function. The following will
suffice:
Code:FUNCTION FindArray ALIAS "FindArray" _ (BYVAL TSArrayPtr AS DWORD ,_ ' Dword that contains a Float Pointer BYVAL TSStartAddr AS DWORD ,_ ' Dword BYVAL TSArraySize AS DWORD ) EXPORT AS SINGLE ' LOCAL ElemAddrSNGPtr AS SINGLE PTR ' Dword Float Ptr, Long, Long, Dword, Dword ElemAddrSNGPtr = FindAddress_Array( TSArrayPtr, 3, 0, TSStartAddr, TSArraySize ) ' Returns Float Pointer FUNCTION = @ElemAddrSNGPtr ' Function Returns a Float END FUNCTION
to get the value of something you can access directly in the "Easy Language"
itself as well as from your PowerBASIC DLL - I take it it's an exercise?
Cheers
Florent
------------------
[This message has been edited by Florent Heyworth (edited April 05, 2001).]
Leave a comment:
-
Lance,
Thx so much for your patient help. As you can tell I am frustrated by this problem. I have spent MANY hours trying to figure it out. Dont worry i do not feel belittled. Any and all help is very welcome.
I read and re-read the posts here. I think I understand the deal with passing pointers Vs. reading the value they point to.
I re-wrote the code and simplified it for this exercise. It now runs without crashing, but the value I get for ArrayElem is 0.
Here it is:
{**********************************************************************************************************}
{ Description : Easy Language program to Test elkit32.dll }
{**********************************************************************************************************}
Vars: Result(0), dwStartAddr(0), dwArraySize(0);
Array: MyArray[15](987); { fill array with 987 }
DefineDLLFunc: "Test.dll", float, "FINDARRAY", LPFLOAT, DWORD, DWORD ;
{============================================== S T A R T ===============================================}
If currentBar < 5 then Begin
MyArray[CurrentBar] = CurrentBar*79 ; {fill an array element with some number }
dwStartAddr = ArrayStartAddr(MyArray);
dwArraySize = ArraySize(MyArray);
{ (LPFLOAT)&MyArray[7], (DWORD)dwStartAddr, (DWORD)dwArraySize }
Result = FindArray( &MyArray[CurrentBar], ArrayStartAddr(MyArray), ArraySize(MyArray) ); { Call Dll }
Print("Bar ",fi(currentBar)," ",fi(&MyArray[CurrentBar])," ",fi(dwStartAddr)," ",fi(dwArraySize)," ",fi(Result));
End ;
{=============================================== E N D ================================================}
'¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
#COMPILE DLL "Test.dll"
#INCLUDE "WIN32API.INC"
DECLARE FUNCTION FindAddress_Array LIB "elkit32.dll" ALIAS "FindAddress_Array" _
(lpArray AS DWORD, ElemOfs AS LONG, BarOfs AS LONG, StartAddr AS DWORD, ArraySize AS DWORD) AS DWORD
'¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
FUNCTION FINDARRAY(BYVAL TSArrayPtr AS DWORD ,_ ' Dword that contains a Float Pointer
BYVAL TSStartAddr AS DWORD ,_ ' Dword
BYVAL TSArraySize AS DWORD )EXPORT AS SINGLE '
LOCAL ArrayElem AS SINGLE, ElemAddrPtr AS DWORD, ElemAddrSNGPtr AS SINGLE PTR
' Dword Float Ptr, Long, Long, Dword, Dword
ElemAddrPtr = FindAddress_Array( TSArrayPtr, 3, 0, TSStartAddr, TSArraySize ) ' Returns Float Pointer
ElemAddrSNGPtr = ElemAddrPtr ' xfer SINGLE PTR from DWORD storage to a SINGLE PTR variable
ArrayElem = @ElemAddrSNGPtr ' read the value of the the SINGLE from memory
FUNCTION = ArrayElem ' Function Returns a Float
END FUNCTION
'¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
Results:
Bar 1 44428368 44428300 8 0
Bar 2 44428376 44428300 8 0
Bar 3 44428384 44428300 8 0
Bar 4 44428392 44428300 8 0
Are these addresses Decimal memory addresses that need to be converted to Hex? do they look plausible?
------------------
Kind Regards
Mike
Leave a comment:
-
Mike, I'm not trying to belittle you, but I think you may need to study the contents of this thread more carefully. It seems to me that you are having two intertwined problems: confusion about a pointer and it's target; and the differences (effects of) passing parameters BYVAL and BYREF with regard to pointers.
To be clear, a pointer is itself stored as a DWORD (32-bit value). You can assign it's value to a pointer variable (which is itself stored as a DWORD), and vice-versa. In this situation, the type of data referenced by the pointer is irrelevent. It only becomes relevent when we try to access that data.
Consider the following:
Code:DIM a AS SINGLE DIM b AS DWORD DIM c AS SINGLE PTR a = 123! b = VARPTR(a) c = b MSGBOX STR$(@c)
Variable "b" is a DWORD, which is assigned the address of the storage of "a".
Variable "c" is a pointer whose target is a SINGLE precision value.
When we reference the target of the real pointer (@c), we can read the value of the SINGLE precision value from memory, without referencing the actual variable.
Since "b" is only a plain DWORD, it does not work as a pointer, although we know that it's value represents the address that a SINGLE precision value is stored in memory.
Obviously, using an "intermediate" DWORD (as I did above) is not compulsory - you can assign the pointer address directly to the pointer, ie, c = VARPTR(a). However, I did so as to describe how the pointer's target address data can be received by your PB function.
The problem (seems to me) that you are having problems grasping what your function is receiving (data or a pointer to the data), and what you are passing to the DLL.
Since your code appears to have been revised substantially since this thread started, we'll need to see it all (since you have not provided the DECLARE you _now_ using for the DLL, nor the code you are using to call your PB function).
Therefore, I think we are going to need to see *exactly* where you are up to now in order to help you rather than confuse the issue!
I hope this helps!
------------------
Lance
PowerBASIC Support
mailto:[email protected][email protected]</A>
Leave a comment:
-
I modified the the code:
FUNCTION FindArray(BYVAL TSArrayPtr AS SINGLE,_
BYVAL TSStartAddr AS DWORD ,_
BYVAL TSArraySize AS DWORD )EXPORT AS SINGLE '
LOCAL ElemAddrPtr AS DWORD ptr, ArrayElem AS SINGLE
ElemAddrPtr = FindAddress_Array( TSArrayPtr, 0, 0, TSStartAddr, TSArraySize )
ArrayElem = @ElemAddrPtr ' dword pointer to the value of specified Array element
FUNCTION = ArrayElem ' return a SINGLE
END FUNCTION
Still says ".. performed illegal operation ..."
------------------
Kind Regards
Mike
Leave a comment:
-
Lance,
How can you do this:
pSingle = lpArray
Dont you need CSNG(lpArray) or are all pointers unsigned 4 byte numbers?
In which case whats the point of having a SINGLE PTR and a LONG PTR and DWORD PTR if they are the same thing? why not just have PTR
and then why is my DLL doing something illegal?
(Pointers allways have tied me up in knots. I have a headache)
------------------
Kind Regards
Mike
Leave a comment:
-
Mike, we both posted at the same time... possibly you may not have noticed my message.
Your problem is most likely to be the lack of BYVALs on the remaining parameters... Florents code shows the correct syntax you need for these parameters.
------------------
Lance
PowerBASIC Support
mailto:[email protected][email protected]</A>
Leave a comment:
-
I have achieved a level of success but I think I understand what the problem is - PB will not allow SINGLE PTR as a return from a function.
The following runs - it does not do what i want, but dlls are called successfully and values pushed around etc etc.
If I uncover the 2 commented lines of code that would give the array Element, TS crashes with "performed illegal operation"
PB Code:
'¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
#COMPILE DLL "Test.dll"
#INCLUDE "WIN32API.INC"
DECLARE FUNCTION FindAddress_Array LIB "elkit32.dll" ALIAS "FindAddress_Array" _
(lpArray AS SINGLE, EOfs AS LONG, BOfs AS LONG, StartAddr AS DWORD, ArraySize AS DWORD) AS DWORD
'¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
FUNCTION LibMain(BYVAL hInstance AS LONG, BYVAL fwdReason AS LONG, BYVAL lpvReserved AS LONG) EXPORT AS LONG
SELECT CASE fwdReason
CASE %DLL_PROCESS_ATTACH
LibMain = 1
CASE %DLL_PROCESS_DETACH
END SELECT
END FUNCTION
'¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
FUNCTION FindArray( TSArrayPtr AS SINGLE,_
BYVAL TSStartAddr AS DWORD ,_
BYVAL TSArraySize AS DWORD )EXPORT AS SINGLE '
Local ElemAddrPtr AS DWORD ptr, ArrayElem AS SINGLE
ElemAddrPtr = FindAddress_Array( TSArrayPtr, 0, 0, TSStartAddr, TSArraySize )
'ArrayElem = @ElemAddrPtr ' dword pointer to the value of specified Array element (causes crash)
'FUNCTION = ArrayElem ' SINGLE (causes crash)
FUNCTION = CSNG(ElemAddrPtr)
END FUNCTION
'¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
TradeStation Easy Language Code:
{**********************************************************************************************************}
{ Description : Test elkit32.dll }
{**********************************************************************************************************}
Vars: Result(0), dwStartAddr(0), dwArraySize(0);
Array: MyArray[15](987); { fill array with 987 }
DefineDLLFunc: "Test.dll", float, "FindArray", lpfloat, DWord, DWord ;
{============================================== S T A R T ===============================================}
If currentBar < 5 then Begin { just execute for first 4 bars }
MyArray[CurrentBar] = CurrentBar*79 ; {fill an array element with some number }
dwStartAddr = ArrayStartAddr(MyArray);
dwArraySize = ArraySize(MyArray);
{ (LPFLOAT)&MyArray[7], (DWORD)dwStartAddr, (DWORD)dwArraySize }
Result = FindArray( &MyArray[CurrentBar], dwStartAddr, dwArraySize ); { Call Dll }
Print("Bar ",fi(currentBar)," ",fi(&MyArray[CurrentBar])," ",fi(dwStartAddr)," ",fi(dwArraySize)," ",fi(Result));
{ fi = format as integer (all values in EL are floats) }
End ;
{=============================================================================================}
Results:
Bar 1 44482064 44481996 8 1524915968
Bar 2 44482072 44481996 8 1524915968
Bar 3 44482080 44481996 8 1524915968
Bar 4 44482088 44481996 8 1524915968
------------------
Kind Regards
Mike
Leave a comment:
-
Either way will work, as long as you use the value is the correct context.
That is, the DLL is being sent the actual pointer target address. So you can receive it as a BYVAL DWORD (and then assign the value to a pointer of the appropriate type), or you can receive it directly as a pointer instead.
Method 1:
Code:FUNCTION FindArray( BYVAL lpArray AS DWORD,... DIM pSingle AS SINGLE PTR pSingle = lpArray ' now work with the pointer target MSGBOX STR$(@pSingle) ...
Code:FUNCTION FindArray(pSingle AS SINGLE PTR,... ' now work with the pointer target MSGBOX STR$(@pSingle) ...
Code:FUNCTION FindArray(BYREF sSingle AS SINGLE,... ...
I hope this helps!
------------------
Lance
PowerBASIC Support
mailto:[email protected][email protected]</A>
Leave a comment:
-
Update:
I got my Dll to compile thx to your tips. And it loads when called from TS (which means elkit32.dll has been loaded also.
It then runs but so far the result is not what I expect.
SO I am still lost in the land of pointers.
One thing I do not understand in your example is why you declare lpArray as DWORD and not DWORD PTR.
FUNCTION FindArray( BYVAL lpArray AS DWORD,
You are sending it a PTR so dont you have to declare it as a pointer?
------------------
Kind Regards
Mike
Leave a comment:
-
Wow Florent!
Thats amazing. Ive been struggling with this for days and you just knock out an example like its nothing.
I Understand the SINGLE PTR problem now thx.
Omega says the following about its pointers:
Pointer data types are designed to pass the memory addresses of various data objects to a DLL function. All pointers used in EasyLanguage are treated as 32-bit pointers. To receive a pointer to a data object, the user must precede the data object with an "&".
All pointers are 32-bit pointers and EasyLanguage treats each of them in the same manner.
Also, it is very important to remember that all values in EasyLanguage are floats, except
for the Open, High, Low and Close values, which are integers.
Pointer Types:
LPBYTE Pointer to a BYTE.
LPINT Pointer to an int.
LPWORD Pointer to a WORD.
LPLONG Pointer to a LONG.
LPDWORD Pointer to a DWORD.
LPFLOAT Pointer to a float (in C++ float FAR).
LPDOUBLE Pointer to a double (in C++ double FAR).
LPSTR Pointer to a char.
Does this mean that all pointers are LONGs (hence the LP befor each one) but they point to different types?
I am confused about wether LPFLOAT is a LONG that points to a FLOAT or it is a FLOAT that points to a float.
Since all the array elements are floats I assumed the pointer was a float.
Surely a pointer must be a DWORD (32bit unsigned).
Anyways I tried your .EXE which compiled but when it ran I got the following error:
"This program has performed an illegal operation"
So it found the DLL and executed which is cool, but I think I have to call it when TradeStaion is running an Easy Language program so that it can look up the memory allocated to the array used in that Easy language program.
------------------
Kind Regards
Mike
Leave a comment:
-
Hi Mike
the 1st compile error you'll get is because of your function
prototype for FindAddress_Array where you define the return
type as SINGLE PTR. If the function is returning a pointer
change it to a DWORD or LONG since PowerBASIC does not accept
this syntax.
Additionally you may want to declare an ALIAS for the DECLARE
(depending on the case of Trade Station DLL) otherwise the
loader might not find the name of the exported function.
So your function declaration would look like this:
DECLARE FUNCTION FindAddress_Array LIB "C:\Program Files\Omega Research\Program\elkit32.dll" ALIAS "FindAddress_Array" _
(lpArray AS SINGLE, ElemOffset AS LONG, BarOffset AS LONG, StartAddr AS DWORD, ArraySize AS DWORD) AS DWORD
Secondly you're getting a DEFTYPE error in your wrapper function
FindArray since you have not declared lpElemAddr in your code.
Here's an example based on the declarations in your first message:
Code:'¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ #COMPILE EXE "Test.EXE" #INCLUDE "WIN32API.INC" DECLARE FUNCTION FindAddress_Array LIB "C:\Program Files\Omega Research\Program\elkit32.dll" ALIAS "FindAddress_Array" _ (BYVAL lpArray AS DWORD, BYVAL ElemOffset AS LONG, BYVAL BarOffset AS LONG, BYVAL StartAddr AS DWORD, BYVAL ArraySize AS DWORD) AS DWORD FUNCTION FindArray( BYVAL lpArray AS DWORD, BYVAL lElemOffset AS LONG, _ BYVAL lBarOffset AS LONG, BYVAL dwStartAddr AS DWORD, _ BYVAL dwArraySize AS DWORD) AS SINGLE LOCAL pResult AS SINGLE PTR pResult = FindAddress_Array( lpArray, lElemOffset, lBarOffset, dwStartAddr, dwArraySize ) FUNCTION = @pResult END FUNCTION FUNCTION PBMAIN() AS LONG LOCAL i AS LONG DIM sng(0:10) AS SINGLE LOCAL sngResult AS SINGLE FOR i = 0 TO 10 sng(i) = CSNG(i) + 10.9812 NEXT 'Since I do not know the definitions for StartAddress and ArraySize as defined in "TradeStation Easy Language" 'I'm making some assumptions about both of them sngResult = FindArray(VARPTR(sng(7)), -3, 2, VARPTR(sng(0)), SIZEOF(sng(0)) * ( UBOUND(sng(),1) + 1) ) END FUNCTION
------------------
Leave a comment:
-
Here is the Dll. I get multiple complile errors!
'¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
#COMPILE DLL "Test.DLL"
#INCLUDE "WIN32API.INC"
GLOBAL ElemOffset AS LONG, BarOffset AS LONG
GLOBAL ElemAddr AS SINGLE
GLOBAL ArraySize AS DWORD, StartAddr AS DWORD
DECLARE FUNCTION FindAddress_Array LIB "C:\Program Files\Omega Research\Program\elkit32.dll" _
(lpArray AS SINGLE PTR, ElemOffset AS LONG, BarOffset AS LONG, StartAddr AS DWORD, ArraySize AS DWORD) AS SINGLE PTR
'¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
FUNCTION LibMain(BYVAL hInstance AS LONG, BYVAL fwdReason AS LONG, BYVAL lpvReserved AS LONG) EXPORT AS LONG
SELECT CASE fwdReason
CASE %DLL_PROCESS_ATTACH ' TradeStation loads a Study
LibMain = 1 ' DLL Attached successfully
CASE %DLL_PROCESS_DETACH ' TradeStation unloads the Study and Releases the DLL
END SELECT
END FUNCTION
'¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
FUNCTION FindArray(lpArray AS SINGLE PTR,_ ' Price (Different every bar)
lpStartAddr AS SINGLE PTR,_ ' Price (Different every bar)
lpArraySize AS SINGLE PTR,_ ' Price (Different every bar)
BYVAL TSCurrentBr AS SINGLE,_ ' Bar Number starting at MaxBarsBack
BYVAL TSMaxBrsBk AS SINGLE)EXPORT AS SINGLE' MaxBarsBack for TS Study (Must be greater than MinLkBk !!)
lpArray = lpArray 'SINGLE Pointer
ElemOffset = 0 'LONG Specifies the offset of array elements - forward +ve and backwards -ve
BarOffset = 0 'LONG Bar offset - forward +ve and backwards -ve
StartAddr = @lpStartAddr 'DWORD The starting address of the buffer
ArraySize = @lpArraySize 'DWORD The size of the buffer
lpElemAddr = FindAddress_Array( lpArray,_ ' SINGLE PTR
ElemOffset,_ ' LONG
BarOffset,_ ' LONG
StartAddr,_ ' DWORD
ArraySize) ' DWORD
FUNCTION = @lpElemAddr
END FUNCTION
'¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
------------------
Kind Regards
Mike
Leave a comment:
-
Accessing Array elements in Memory and converting a C++ Dll Declaration
I am trying to get access to Array elements of an Array in EasyLanguage (A language used in TradeStation - a stand alone Application) from my PB Dll.
(Ultimatly I would like to be able to access an array element, do some calculations and then stuff the result back in place of the original element so i can have access to it in EasyLanguage)
Anyways, Part1 of this problem is to get access to an array element in my PB Dll. Omega (who make TradeStation) have a developers kit (a Dll) for C++ and VB users. Here is what they say about accessing array elements:
ELKIT32.DLL
Functionality
The EasyLanguage Tool Kit Library is implemented in the form of a dynamic-link library. It provides useful functions that can be called from any user DLL. It is commonly used to find the address of an offset of an EasyLanguage data object from within a user DLL.
Components
There are four components in the EasyLanguage Tool Kit Library: a header file (ELKIT32.H), two link-time library files (ELKITVC.LIB and ELKITBOR.LIB), and an executable DLL file (ELKIT32.DLL). 'ELKIT32.H' is a standard C header file. It contains the function headers for all the functions that are available in 'ELKIT32.DLL'. The '.LIB' files should be used when linking a user DLL that calls the ELKIT32.DLL functions. 'ELKITVC.LIB' should be used when working in the Microsoft Visual C++ environment while 'ELKITBOR.LIB' should be used in the C++ Builder environment.
Functions Available:
FindAddress_Array
FindAddress_Open
FindAddress_Close
FindAddress_OpenInt
FindAddress_Date
FindAddress_Time
FindAddress_DownTicks
FindAddress_UpTicks
FindAddress_High
FindAddress_Var
FindAddress_Low
FindAddress_Volume
...................................................................................................................................
FindAddress_Array:
LPFLOAT FindAddress_Array( LPFLOAT lpArray[ArrayPosition], int nSpaceOfs, int nOfs, DWORD wStartAddr, DWORD wArraySize );
Parameters:
lpArray
A pointer to an Array in EasyLanguage.
nSpaceOfs
Specifies the offset of array elements. The offset is forward if nSpaceOfs is positive and backwards if nSpaceOfs is negative.
nOfs
Specifies the bar offset. The offset is backwards if Ofs is positive or forward if Ofs is negative.
wStartAddr
The starting address of the buffer as determined by the EasyLanguage keyword ArrayStartAddr.
wArraySize
The size of the buffer associated with the array as determined by the EasyLanguage keyword ArraySize.
Returns:
A pointer to the value of an Array element offset by nOfs.
Remarks:
wArraySize is the size of the buffer associated with the array. This value is obtained from EasyLanguage by calling the ArraySize function. wStartAddr is the starting address of the buffer. The ArrayStartAddr function should be called to obtain this value.
....................................................................................................................................
{ Omega Research TradeSatation EasyLanguage Example }
DefineDLLFunc: "MYLIB.DLL",float,"FindArray",multiple;
Var: wStartAddr(0), wArraySize(0),Counter(0), Result(0);
Array: MyArray [10](0);
If CurrentBar = 11 then Begin
For Counter = 0 to 10 Begin
MyArray[Counter] = Close[Counter];
End;
End;
wStartAddr = ArrayStartAddr(MyArray);
wArraySize = ArraySize(MyArray);
Result = FindArray((LPFLOAT)&MyArray[7], (int) -3, (int) 2, (DWORD)wStartAddr, (DWORD)wArraySize );
Plot1(Result, "FindArray");
...................................................................................................................................
// Example of FindAddress_Var in MYLIB.DLL
// starting at element 7, go back 3 elements and 2 bars
float FindArray( LPFLOAT lpVar, int nSpaceOfs, int nOfs, DWORD wStartAddr, DWORD wArraySize )
{
LPFLOAT lpNewAddr;
lpNewAddr = FindAddress_Array(lpArray, nSpaceOfs, nOfs, wStartAddr, wVarSize);
return *lpNewAddr;
}
...................................................................................................................................
So first I want to declare the elkit32.dll in my Dll. I tried like this:
DECLARE FUNCTION FindAddress_Array LIB "C:\Program Files\Omega Research\Program\elkit32.dll" _
(lpArray AS SINGLE PTR, nSpaceOfs AS INTEGER, nOfs AS INTEGER, wStartAddr AS DWORD, wArraySize AS DWORD) AS SINGLE PTR
But I get the error - "end of Statement expected"
So thats my first question.
Second is: Once I have declared the function FindAddress_Array in the elkit32.dll and then called it with
lpNewAddr = FindAddress_Array(lpArray, nSpaceOfs, nOfs, wStartAddr, wVarSize
can I just get the array element with:
Element = @ lpNewAddr
And Finally, can i put a new value in that memory location with:
lpNewAddr = VARPTR(SomeNewValue)
and be able to retrieve SomeNewValue in the TradeStation EasyLanguage Array Element?
------------------
Kind Regards
MikeTags: None
Leave a comment: