Announcement

Collapse
No announcement yet.

Accessing Array elements in Memory and converting a C++ Dll Declaration

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    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
    Mike

    #2
    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

    Comment


      #3
      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

      ------------------

      Comment


        #4
        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

        Comment


          #5
          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

          Comment


            #6
            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)
              ...
            Method 2: (Note that a pointer can only ever be received BYVAL, so the BYVAL is implied and handled automatically by the PB)
            Code:
            FUNCTION FindArray(pSingle AS SINGLE PTR,...
              ' now work with the pointer target
              MSGBOX STR$(@pSingle)
              ...
            Method 3: Receive the value BYREF
            Code:
            FUNCTION FindArray(BYREF sSingle AS SINGLE,...
              ...
            Finally, the default parameter passing method for C is BYVAL, whereas PB's default is BYREF - be sure to use the correct method in your declarations and prototypes.

            I hope this helps!

            ------------------
            Lance
            PowerBASIC Support
            mailto:[email protected][email protected]</A>
            Lance
            mailto:[email protected]

            Comment


              #7
              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

              Comment


                #8
                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>
                Lance
                mailto:[email protected]

                Comment


                  #9
                  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

                  Comment


                    #10
                    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

                    Comment


                      #11
                      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 "a" is the actual SINGLE precision data.
                      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>
                      Lance
                      mailto:[email protected]

                      Comment


                        #12
                        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

                        Comment


                          #13
                          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
                          I actually don't understand the point of calling elkit32.dll at all
                          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).]

                          Comment


                            #14
                            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

                            Comment

                            Working...
                            X
                            😀
                            🥰
                            🤢
                            😎
                            😡
                            👍
                            👎