Announcement

Collapse
No announcement yet.

Returning QUAD for C++ compilers

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

  • Returning QUAD for C++ compilers

    Hi All,

    I have created a PB DLL which has functions that return QUAD values. However, Visual C++ doesn't seem to read the return value correctly. I am using the __INT64 type in C and it returns 0 instead of any correct value. I was wondering if anyone has encountered this before and what the solution is? Returning another type (such as DWORD) is not an option.


    ------------------
    contact me
    kgpsoftware.com - Free and Commercial Software

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

  • #2
    Kev,

    What has the __INT64 been mapped from? All my C/C++ data has the
    64bit integer defined as __int64 (lowercase).

    The 64bit value can be compiler specific because the quad integer
    is not standard in C/C++. You may need to manipulate the high and
    low values to get C/C++ to function properly.

    Never used quads before in C, so hope this helps.

    Cheers

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


    [This message has been edited by Cecil L. Williams (edited March 13, 2006).]

    Comment


    • #3
      Cecil,

      Sorry, yes I am using the lower-case "__int64". According to the VC++ docs, their int64 type has the same range as PB's QUAD, so I don't know why the problem. Maybe there is an alignment setting that needs to be changed.

      I'm having the same trouble with VB6 and QUADs as well, in that compiler I use CURRENCY type but still get the wrong values.

      ------------------
      contact me
      kgpsoftware.com - Free and Commercial Software
      kgpsoftware.com | Slam DBMS | PrpT Control | Other Downloads | Contact Me

      Comment


      • #4
        If you can't get it to work the 'ideal' way, you could always return the High and Low DWORDS separately and put 'em back togther.

        Or, still on this track, pass the _int64 by reference as a parameter and return it there instead of as the FUNCTION's return value...



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

        Comment


        • #5
          Michael,

          The strange thing is: I can pass the __int64's as parameters (either BYVAL or BYREF) but am having no luck returning them. It's really got me stumped

          ------------------
          contact me
          kgpsoftware.com - Free and Commercial Software
          kgpsoftware.com | Slam DBMS | PrpT Control | Other Downloads | Contact Me

          Comment


          • #6
            Kev,

            According to my VC6 docs, the currency value should work in VB.

            Have you rechecked your PB code to see if the value set is what
            you want or should be?

            Best results in returning to C/C++ is BYVAL, since that is the standard
            passing convention. Have you tried passing a pointer from PB to
            C and vice-versa?

            Cheers

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

            Comment


            • #7
              I can pass the __int64's as parameters (either BYVAL or BYREF) but am having no luck returning them.
              You mean you can't return _int64 as the return value of the function, right?

              Because if you can pass _int64 BYREF as a parameter, you can change it.

              So do that instead of accumulating angst about getting it to work as the "return value of the function."

              Besides, I read above that 64-bit binary integers are not a 'C' standard datatype (I do not write in C). Seems to be you end up with more portable code if you go the BYREF route.


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

              Comment


              • #8
                We pass quads back and forth to VC++ byref all of the time. The C declartion in the .h file looks like this:

                extern "C" ErrorCode PASCAL EXPORT AVD_ConvertFrames2SizeMB(DWORD rFrames, DWORD FormatNumber, DWORD *VideoReservedSpace, DWORD *AudioReservedSpace);

                The PowerBasic declaration looks like this:

                DECLARE FUNCTION AVD_ConvertFrames2SizeMB LIB "avdserialdigital.dll" ALIAS "AVD_ConvertFrames2SizeMB"(BYVAL Frames AS LONG,BYVAL FormatType AS LONG,BYREF VidSpace AS QUAD,BYREF AudSpace AS QUAD) AS LONG

                Hope that helps,
                Russ


                ------------------
                "There are two novels that can change a bookish fourteen-year old's life: The Lord of the Rings and Atlas Shrugged. One is a childish fantasy that often engenders a lifelong obsession with its unbelievable heroes, leading to an emotionally stunted, socially crippled adulthood, unable to deal with the real world. The other, of course, involves orcs." - John Rogers

                Comment


                • #9
                  Russ,

                  Just said that above. Your C++ function has been proto'd as a pointer
                  and you're passing the address in PB, same same. The standard
                  passing convention in C/C++ is "byval" and address passing is (aka
                  byref) by pointer.

                  I would surmise that Kev has prob in his PB code since the VB
                  currency data type doesn't work either, as he mentioned above.

                  Cheers

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

                  Comment


                  • #10
                    Russ, fi you actually pass a value greater than 32-bits you are going to see problems.

                    Comment


                    • #11
                      Guys,

                      Thanks for the responses. I am surprised that no-one has come across this before.

                      I haven't found a solution as yet, and I posted to some C-language newsgroups and created a sample project, here:

                      http://www.kgpsoftware.com/downloads/quadprob.zip

                      Run "quadtest".exe, as you can see, I'm getting random values back. I'm beginning to think 64-bit return values aren't supported, which is a shame and means a lot of code rewrites.

                      ------------------
                      contact me
                      kgpsoftware.com - Free and Commercial Software
                      kgpsoftware.com | Slam DBMS | PrpT Control | Other Downloads | Contact Me

                      Comment


                      • #12
                        >According to my VC6 docs, the currency value should work in VB.

                        Then that should work fine with PB, since PB currency is the same 64-bit scaled twos-complement binary integer.

                        But if you need more range (i.e, the decimals are meaningless and you'd rather have those four decimal digits BEFORE the decimal point) there's no reason that you can't SCALE a quad in your PB function before returning it.

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

                        Comment


                        • #13
                          If it helps Kev, I have tested VC6's __int64 with PB's QUAD and
                          they are compatible so as suggested it appears your PB code needs to be
                          checked to ensure you are not mismatching byval and byref parameters.


                          This appears to work, Kev.

                          Code:
                          typedef __int64 __stdcall doquad( __int64 q, __int64 *q2);
                          doquad*	pdoquad;
                          
                          int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
                          {
                              HINSTANCE hDoQuad;
                              __int64 q = 5000000000000;
                              __int64 q2 = 10000000000000;
                              __int64 ret;
                          
                              hDoQuad = LoadLibrary("e:/PBWIN70/testApps/TestQuad.dll");
                              pdoquad = (doquad* ) GetProcAddress(hDoQuad,"doquad");
                          
                              ret = pdoquad( q, &q2 );
                          }
                          
                          PB DLL Code
                          -----------
                          #Dim All
                          #Option Version5
                          #Compile Dll
                           
                          Declare Function doquad Alias "doquad" (ByVal q As Quad, ByRef q2 As Quad ) As Quad
                               
                          Function PBMain
                              Function = 0
                          End Function
                           
                          Function doquad ( ByVal q As Quad, ByRef q2 As Quad ) Export As Quad
                              Dim qp As Quad Ptr
                              Dim s As String * 8
                              Dim ss As String
                              Dim l As Long
                           
                              qp = VarPtr(q)
                           
                              s = Peek$( qp, 8 )
                           
                              ss = "Q:" & Str$(q) & $CrLf & "Q2:" & Str$(q2) & $CrLf
                              
                              For l = 1 To 8
                                  ss = ss & Hex$(Asc(s,l),2) & " "
                              Next
                           
                              MsgBox ss
                              incr q
                              Function = q
                          End Function

                          [This message has been edited by Ron Pierce (edited March 17, 2006).]

                          Comment


                          • #14
                            "If you actually pass a value greater than 32-bits you are going to see problems."
                            Don't thing so, as Cecil said, we're passing a 32 bit pointer to a quad word variable. The variable could be any type as long as the c++ guy and I agree on the type.

                            Russ

                            ------------------
                            "There are two novels that can change a bookish fourteen-year old's life: The Lord of the Rings and Atlas Shrugged. One is a childish fantasy that often engenders a lifelong obsession with its unbelievable heroes, leading to an emotionally stunted, socially crippled adulthood, unable to deal with the real world. The other, of course, involves orcs." - John Rogers

                            Comment


                            • #15
                              I did get the VB stuff working correctly by using a "Enable VB"-type function, and translating the values using code similar to this (psuedo):

                              Code:
                              Sub EXPORTED_SUB(ByVal i64 As Quad) EXPORT
                               
                                  If IsVB Then
                                     ' Translate the VB currency type to 64-bit integer...
                                     Local pCur As Currency Ptr
                                     pCur = VarPtr(i64)
                                     i64 = CQud(@pCur)
                                  End If
                               
                                  MsgBox "INT64 Value: " + Str$(i64)
                              End Sub
                              This still means a lot of work though, for VB support.

                              ------------------
                              contact me
                              kgpsoftware.com - Free and Commercial Software
                              kgpsoftware.com | Slam DBMS | PrpT Control | Other Downloads | Contact Me

                              Comment


                              • #16
                                Ron, Thanks a lot for the code.

                                If it works using LoadLibrary/GetProcAddress then it should work using a .LIB file. VC++ expects the return value for __int64 to be returned in the edx:eax registers, but PB seems to not do that. Could this be a bug, or just a compatibility issue?

                                Added: Here is the thread I posted on the microsoft.public.vc.language newsgroup:

                                http://groups.google.co.uk/group/mic...379e01580b9caf

                                ------------------
                                contact me
                                kgpsoftware.com - Free and Commercial Software

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

                                Comment


                                • #17
                                  VC++ expects the return value for __int64 to be returned in the edx:eax registers, but PB seems to not do that. Could this be a bug, or just a compatibility issue?
                                  Seems to me you should direct your question to PB Support.

                                  After all, since they market the product to support "write assembly language routines" it seems logical they should tell you how (in which registers) to return what kinds of results.

                                  I would swear I saw such a table in a prior version of the compiler's help file, but I can't find it for the 7x version.

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

                                  Comment


                                  • #18
                                    Well, I thought they may be monitoring this thread. By the way, this test works correctly for Visual C:

                                    Code:
                                    #Compile Dll "release\quad_dll.dll"
                                    #Dim All
                                     
                                    Function TEST(ByVal i As Long) Export As Quad
                                     
                                      Local dwRet As Dword
                                     
                                      dwRet = 0
                                      ! MOV EDX, dwRet
                                      dwRet = i
                                      ! MOV EAX, dwRet
                                     
                                    End Function
                                    But it doesn't work when calling from a PB EXE, but I can work around that. Now the question is: is that method safe to use?

                                    Additionally, the LO() function doesn't support QUAD values, but MAK() does. New feature suggestion?

                                    ------------------
                                    contact me
                                    kgpsoftware.com - Free and Commercial Software
                                    kgpsoftware.com | Slam DBMS | PrpT Control | Other Downloads | Contact Me

                                    Comment


                                    • #19
                                      try:
                                      MyDword0 = LO(DWORD, MyQuad))
                                      MyDword1 = HI(DWORD, MyQuad))

                                      for WORDs in a QUAD:

                                      MyWord0 = LO(WORD, LO(DWORD, MyQuad))
                                      MyWord1 = Hi(WORD, LO(DWORD, MyQuad))
                                      MyWord2 = LO(WORD, HI(DWORD, MyQuad))
                                      MyWord3 = HI(WORD, HI(DWORD, MyQuad))

                                      The type QUAD isn't mentioned in Help, but LO(LONG and LO(DWORD can
                                      only be parts of a QUAD. First line in Help "... an integer-class value."
                                      Quad is an integer-class value.

                                      Cheers,


                                      ------------------
                                      Dale
                                      Dale

                                      Comment


                                      • #20
                                        hmm of course, sorry about that.

                                        btw. i found this old thread in poffs. it explains the return values i'm seeing:

                                        http://www.powerbasic.com/support/pb...ead.php?t=1895

                                        running some more tests, the mov edx/eax code i posted is not reliable after so many calls. any help on fixing this would be appreciated.

                                        ------------------
                                        contact me
                                        kgpsoftware.com - free and commercial software

                                        [this message has been edited by kev peel (edited march 15, 2006).]
                                        kgpsoftware.com | Slam DBMS | PrpT Control | Other Downloads | Contact Me

                                        Comment

                                        Working...
                                        X