Announcement

Collapse
No announcement yet.

C++ To PB

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

  • C++ To PB

    I'm trying to export a function in a C++ 6.0 DLL to call in PB.

    I have an exported function(exported in a .def file) in C++(DLL name "testlib.dll"):

    char* MyFunc()
    {
    char *szText = "b1b7a3805872df8323d03be54764a314";
    return szText;
    }

    And in PB I declare it like:
    DECLARE FUNCTION MyFunc LIB "testlib.dll" ALIAS "MyFunc" () AS STRING 'STRING because the compiler errors when I do ASCIIZ * anything

    And call it like:
    GLOBAL szTest AS STRING 'also tried AS ASCIIZ * 32 since the string is 32 chars in length, but didnt work

    szTest = MyFunc()

    but it only logs the first 3 or 4 chars in the entire string.

    I can't figure this out.

    Any suggestions?

    Thanks.

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


    [This message has been edited by Jay Straffer (edited July 28, 2007).]

  • #2
    Have you tried:
    Code:
    DECLARE FUNCTION MyFunc LIB "testlib.dll" ALIAS "MyFunc" () AS DWORD
    GLOBAL szPtr As Asciiz Ptr
    szPtr = MyFunc()
    MsgBox @szPtr
    ------------------
    Regards,
    Peter
    Regards,
    Peter

    Comment


    • #3
      Works perfect. Thank you very much.

      Also, is it possible to do vectors in PB?

      Like: vector<char*> blah;

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


      [This message has been edited by Jay Straffer (edited July 28, 2007).]

      Comment


      • #4
        Hello Jay,

        I don't know vectors. (Never used them in C) I looked briefly at them and if I am correct it is some kind of byte array?


        ------------------
        Regards,
        Peter
        Regards,
        Peter

        Comment


        • #5
          As far as I can see, is vector<char*> an array of asciiz string pointers.
          If so, you can use:
          Code:
          DECLARE FUNCTION MyFunc LIB "testlib.dll" ALIAS "MyFunc" () AS DWORD
          GLOBAL szPtr As Asciiz Ptr
          szPtr = MyFunc()
          MsgBox @szPtr[0]    'First element
          MsgBox @szPtr[1]    'Second element
                              'etc....
          ------------------
          Regards,
          Peter
          Regards,
          Peter

          Comment


          • #6
            The way you are using szText is very "dangerous" since it is deallocated as soon as the function returns. You should either define szText as static or global in the C code and then return the address. Alternatively, the API function GlobalAlloc(%GPTR, <size> ) will allocate a dynamic buffer that can be freed by your PB application using GlobalFree. You could even (gasp ) specify a string buffer as a byref parameter. The last two methods are thread-safe too.

            Whilst it appears to work now, since the stack memory it points to has been freed, it can be overwritten quite easily by further stack usage.

            ------------------
            kgpsoftware.com - Downloads
            kgpsoftware.com - Development and Consulting

            [This message has been edited by Kev Peel (edited July 29, 2007).]
            kgpsoftware.com | Slam DBMS | PrpT Control | Other Downloads | Contact Me

            Comment


            • #7
              Code:
              DECLARE FUNCTION MyFunc LIB "testlib.dll" ALIAS "MyFunc" () AS DWORD
              GLOBAL szPtr As Asciiz Ptr
              szPtr = MyFunc()
              MsgBox @szPtr
              
              ...
              > Works perfect[ly].

              Someone has to deallocate the memory at szPtr. (Unless you want a memory leak).




              [This message has been edited by Michael Mattias (edited July 29, 2007).]
              Michael Mattias
              Tal Systems (retired)
              Port Washington WI USA
              [email protected]
              http://www.talsystems.com

              Comment


              • #8
                I suppose the C DLL should have a function like Deallocate_Memory(szPtr)...


                ------------------
                Regards,
                Peter
                Regards,
                Peter

                Comment


                • #9
                  How would I deallocate memory in PB?

                  Sorry for the dumb questions.

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

                  Comment


                  • #10
                    > How would I deallocate memory in PB?

                    I also thought about that, but for that you would have to know how the DLL allocated the memory (GlobalAlloc, HeapAlloc, etc...),
                    in order to be able to free it. (I think, correct me if I'm wrong...)

                    ------------------
                    Regards,
                    Peter
                    Regards,
                    Peter

                    Comment


                    • #11
                      I also thought about that, but for that you would have to know how the DLL allocated the memory (GlobalAlloc, HeapAlloc, etc...),
                      in order to be able to free it. (I think, correct me if I'm wrong...)
                      That is correct. You have to know how it was allocated to deallocate it.

                      I think some writers create these functions to allocate the first time and reallocate each subsequent entry (e.g., like using a STATIC variable). You'll know that to be the case if the documentation tells you the pointer returned is valid until the next time you call the function.

                      I'll give you a real good example of why you have to know: Mercator returns a pointer to the data it gives you which is obtained using the GlobalAllocPtr macro. You are not responsible for deallocating with Mercator, nor are you permitted to modify the data (you wouldn't want to anyway), but that's the kind of variation you can expect in "how" memory is allocated.

                      FYI: GlobalAllocPtr = GlobalLock(GlobalAlloc (flags, size)), returns ptr

                      The deallocation function required here is three statements:
                      Code:
                      hMem = GlobalHandle(ptr) 
                      GlobalUnlock hMem
                      GlobalFree   hMem

                      Michael Mattias
                      Tal Systems (retired)
                      Port Washington WI USA
                      [email protected]
                      http://www.talsystems.com

                      Comment


                      • #12
                        Thanks for all the replies guys. Appreciate it.

                        As for the vectors thing.

                        say like, in C++ I do:
                        #include <vector>
                        using namespace std;

                        vector<char*> myStuff; //this way, using vectors, it holds info i enter in it

                        //then enter information in the vector:
                        char *szTxt1 = "whale";
                        char *szTxt2 = "blubber";
                        myStuff.push_back(szTxt1);
                        myStuff.push_back(szTxt2);

                        //then if i want to search in the vector for a string:
                        for (int n = 0; n < myStuff.size(); n++)
                        {
                        if (!strcmp("blubber",myStuff.at(n)))
                        MessageBox(0, "It's there!", 0, 0);
                        }

                        I was just wondering if such a thing was possible in PowerBasic.

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




                        [This message has been edited by Jay Straffer (edited August 02, 2007).]

                        Comment


                        • #13
                          "IF" a vector thing is an array of (ASIIIZ) string pointers (I don't know from vectors), then you can search that array like any other...
                          Code:
                            LOCAL pAZ AS ASCIIZ PTR 
                          
                            Call function which returns pointer to first element 'pV' and number of elements 'nV'
                          
                            pAz =     pv   
                            FOR Z = 1 TO nV 
                              if @pAz = "target text"  THEN  ' or search within with INSTR or whatever
                                bFound = %TRUE
                                FoundAt = Z 
                                EXIT FOR
                              else
                                INCR pAZ   ' move to next element
                              end if
                            next
                            if bfound then 
                              Message "found target text at element 'found at' ...
                              ...
                            else
                               message "not found"
                            ....

                          [This message has been edited by Michael Mattias (edited August 02, 2007).]
                          Michael Mattias
                          Tal Systems (retired)
                          Port Washington WI USA
                          [email protected]
                          http://www.talsystems.com

                          Comment


                          • #14
                            Michel Mattias, I appreciate your help but I don't seem to
                            understand what that is doing or how it works fully.

                            Is there any way to store multiple info(strings for instance)
                            without using vectors?

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


                            [This message has been edited by Jay Straffer (edited August 03, 2007).]

                            Comment


                            • #15
                              >Is there any way to store multiple info(strings for instance)
                              without using vectors?

                              You can do it without the extra level of indirection, that is you don't
                              need to use an array of pointers to the data, you can just put the data directly
                              into a dynamic string array. The individual strings can be of almost any length:

                              Code:
                              DIM dynamStringArr(100) AS STRING
                                 dynamStringArr(0) = "short string"
                                 dynamStringArr(1) = "still a short string"
                                 dynamStringArr(2) = "longer string longer string longer string longer string longer string"
                                 'then access the data easily:
                                 MSGBOX dynamStringArr(1)
                              The string array could also be ASCIIZ strings, just be sure to dimension the string length
                              big enough to handle your longest string, plus 1 for the null terminator:

                              Code:
                              DIM asciizStringArr(100) AS ASCIIZ * 51 '<< string up to 50 chars long
                                 asciizStringArr(0) = "short string"
                                 asciizStringArr(1) = "still a short string"
                                 asciizStringArr(2) = "longer string longer string longer string longer s"
                                 'then access the data easily:
                                 MSGBOX asciizStringArr(1)



                              [This message has been edited by John Gleason (edited August 03, 2007).]

                              Comment


                              • #16
                                John, is there a way to search the entire array instead of just 1 at a time?

                                Like:

                                DIM asciizStringArr(100) As ASCIIZ * 51
                                asciizStringArr(0) = "howdy"
                                asciizStringArr(1) = "blah"
                                asciizStringArr(2) = "hello"

                                IF INSTR(asciizStringArr(),"blah") THEN
                                MSGBOX "yes"
                                ELSE
                                MSGBOX "no"
                                END IF

                                although this does not work.

                                I sure do wish PB allowed use of vectors.

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




                                [This message has been edited by Jay Straffer (edited August 03, 2007).]

                                Comment


                                • #17
                                  See ARRAY SCAN in the help file...

                                  ------------------
                                  Adam Drake
                                  Drake Software

                                  Comment


                                  • #18
                                    As Adam suggested, you could do it as follows. It tells you
                                    the array element + 1 where a match was found:
                                    '
                                    Code:
                                    #COMPILE EXE
                                    #DIM ALL
                                    
                                    FUNCTION PBMAIN () AS LONG
                                      LOCAL foundAt AS LONG
                                      DIM asciizStringArr(100) AS ASCIIZ * 51
                                      asciizStringArr(0) = "howdy"
                                      asciizStringArr(1) = "blah"
                                      asciizStringArr(2) = "hello"
                                    
                                      ARRAY SCAN asciizStringArr(), = "howdy", TO foundAt
                                    
                                      IF foundAt > 0 THEN 'note foundAt will = 1, not 0 because it's a relative index
                                           MSGBOX "yes" & $CRLF & FORMAT$(foundAt)
                                      ELSE
                                           MSGBOX "no"
                                      END IF
                                    
                                    END FUNCTION
                                    '
                                    Another technique you could use is to overlap your array in memory with
                                    a separate string, then search that string for a match:

                                    '
                                    Code:
                                    #COMPILE EXE
                                    #DIM ALL
                                    
                                    FUNCTION PBMAIN () AS LONG
                                      LOCAL foundAt AS STRING, foundPtr AS LONG PTR
                                    
                                      foundAt = SPACE$(6000) 'make it at least as long as your array total memory size
                                      foundPtr = STRPTR(foundAt)
                                      DIM asciizStringArr(100) AS ASCIIZ * 51 AT foundPtr 'Now the array and string overlap in memory
                                    
                                      asciizStringArr(0) = "howdy"
                                      asciizStringArr(1) = "blah"
                                      asciizStringArr(2) = "hello"
                                    
                                      IF INSTR(foundAt,"blah") THEN
                                           MSGBOX "yes" & $CRLF & FORMAT$(INSTR(foundAt,"blah"))
                                      ELSE
                                           MSGBOX "no"
                                      END IF
                                    
                                    END FUNCTION
                                    '
                                    ------------------

                                    Comment


                                    • #19
                                      Here's how arrays differ from vectors in C++.
                                      ARRAYS:
                                      1. Have a fixed size specified in the declaration.
                                      2. Are faster than vectors.
                                      3. You can not add or delete items from an array.
                                      4. Syntax is simpler.
                                      5. Have no safety margin: if an index has wrong value, you crash.

                                      So to "match" a vector in PB you can:
                                      1. REDIM PRESERVE the array to change size.
                                      2. Speed may be faster than C++ vector.
                                      3. With your REDIM'd array you can add or delete items.
                                      4. A little more code probably necessary.
                                      5. Could use UBOUND LBOUND for some safety margin.

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

                                      Comment


                                      • #20
                                        Thanks alot John. I appreciate this very much.

                                        Is it possible to delete an item out of the array?

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

                                        Comment

                                        Working...
                                        X