Announcement

Collapse
No announcement yet.

C to PB conversion problem

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

  • C to PB conversion problem


    I've hit a brick wall. In calling a "C" dll, not C++ or Com, one
    of the functions returns a pointer to a type. The data is returned
    without a problem but a subsequent call to a function is required
    to free the pointer/data. This is where my problem occurs. The memory
    is not being released although the data in the type is being zeroed out.
    This function is call roughly 3000 times a minute and watching the
    memory grow in the task manager is daunting. I have compiled the
    "C" sample code and it does indeed release the memory properly. Any
    ideas would be appreciated. Below is my translations and a snippet
    of code showing how the functions are being called.

    I have tried it on ME, WinNT 4.0 and Win2000 to insure that it is
    not a platform issue.

    Code:
    'typedef struct
    '{
    '   int iType;
    '   const char* szItem;
    '   LPVOID lpData;
    '   DWORD dwDataLen;
    '   const char* szDataFormat;
    '} TALConvData;
    TYPE TALConvDataType
        iType        AS LONG
        szItem       AS ASCIIZ PTR
        lpData       AS LONG PTR
        dwDataLen    AS DWORD
        szDataFormat AS ASCIIZ PTR
    END TYPE
    
    'int FAR PASCAL TALConvWaitForData( DWORD dwConv , DWORD dwTimeout );
    'TALConvData* FAR PASCAL TALConvGetData( DWORD dwConv );
    'void FAR PASCAL (TALConvFreeData( TALConvData* pData );
    
    DECLARE FUNCTION TALConvWaitForData LIB "talapi32.dll" ALIAS "TALConvWaitForData"( BYVAL dwConv AS DWORD, BYVAL dwTimeout AS DWORD ) AS LONG
    DECLARE FUNCTION TALConvGetData LIB "talapi32.dll" ALIAS "TALConvGetData"( BYVAL dwConv AS DWORD ) AS LONG 
    DECLARE SUB TALConvFreeData LIB "talapi32.dll" ALIAS "TALConvFreeData"( BYVAL pData AS DWORD )
    
    LOCAL dwConv    AS DWORD
    LOCAL pszText   AS ASCIIZ PTR
    LOCAL pData     AS TALConvDataType PTR
    
    DO
        SLEEP 10    
        DO
            lReturn = TALConvWaitForData( dwConv, 250 )
            pData = TALConvGetData( dwConv )    
            SLEEP 5        
        LOOP WHILE( pData = %NULL )    
        pszText = @pData.lpData    
        ' display the data.  Because we requested
        ' DATA IN the format "TEXT" we can just use printf TO display it.
        SELECT CASE  @pData.iType
        CASE %TALCONV_ADVISE_DATA        
            'Parsed and displayed correctly
            CALL ProcessIncomingData(@pszText)
        CASE %TALCONV_TERMINATE
            CALL AddToListBox ("TALConvAdvise received a Terminate from the server.." )
            EXIT DO
        CASE ELSE
            CALL AddToListBox  ("TALConvAdvise resulted in an unexpected message of type:" & STR$(@pData.iType ))
            EXIT DO
        END SELECT
        'This line apparently does not properly
        'release the memory although the data is
        'zeroed out.
        CALL TALConvFreeData(pData)
    LOOP


    ------------------
    Jim..
    [email protected]
    Jim..

  • #2
    Jim,

    Could it be that you need to call the TALConvFreeData(pData) function
    before EXIT DO in your SELECT CASE struct?



    ------------------
    Bernard Ertl
    Bernard Ertl
    InterPlan Systems

    Comment


    • #3
      Jim,

      The LPVOID data type in "C" is a Pointer to any type, just
      not exclusive to a LONG.

      Without seeing what the C code is doing, my best guess is
      that you have a pointer scoping problem.

      Cheers,
      Cecil

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

      Comment


      • #4
        Jim,
        Just for kicks try TALConvFreeData VARPTR(pData).

        James


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

        Comment


        • #5

          Bern...

          That is taken care of in code below the snippet but thanks for pointing
          that out...

          Cecil...

          It would be my pleasure to email you the "C" code if you don't mind
          looking at it.. It's very brief.. If you have time and don't mind..
          Please email me your email address.. Mine is below... But for what
          it's worth.. The LPVOID lpData member of the UDT can point to
          several different types as you pointed out.. In this case.. It is
          just a pointer to pure ascii data.. In other cases it can be a
          pointer to a linked list.. etc.... I made it a long PTR with the
          thought that I could use to redirect to the "correct" data type.

          J.C....

          Thanks.. I've tried any combination that a mere mortal can think of..
          including that one...




          ------------------
          Jim..
          [email protected]
          Jim..

          Comment


          • #6
            Hey Jim, good to see you back.

            I'm no expert in these matters but it seems it wants a DWORD, which is a pointer to the pointer/data?

            You showed:
            TALConvFreeData(pData)
            But,
            TALConvFreeData(byval VarPtr(pData)) would probably work (??)

            Scott


            ------------------
            Scott
            Scott Turchin
            MCSE, MCP+I
            http://www.tngbbs.com
            ----------------------
            True Karate-do is this: that in daily life, one's mind and body be trained and developed in a spirit of humility; and that in critical times, one be devoted utterly to the cause of justice. -Gichin Funakoshi

            Comment


            • #7
              Hi Scott..

              I've been here.. Just lurking.. Yes, I could use a DWORD PTR or just
              a DWORD for the return but then I have to use MoveMemory to move
              the data into the UDT.. I've actually tried that but the call to
              TALConvFreeData still does not release the memory.. That brickwall
              that I mentioned in my original post has me black and blue right
              now.. Been 4 days now screwing around with this simple task....

              Thanks for the post...


              ------------------
              Jim..
              [email protected]
              Jim..

              Comment


              • #8
                Jim,

                Can you post the original C declaration for the TALConvFreeData
                function?



                ------------------
                Bernard Ertl
                Bernard Ertl
                InterPlan Systems

                Comment


                • #9
                  Hey Jim,
                  Curious, it looks like the data keeps building up during the loop, and
                  dwConv is being used as a parameter when the GETCONVDATA is called....have you tried putting that in the release sub and putting that in the loop??


                  I'm not sure what the code does etc but it seems if you get the data du ring a loop and *if* dwconv is a pointer you will have to release it during the loop....??



                  Scott

                  ------------------
                  Scott



                  [This message has been edited by Scott Turchin (edited May 29, 2001).]
                  Scott Turchin
                  MCSE, MCP+I
                  http://www.tngbbs.com
                  ----------------------
                  True Karate-do is this: that in daily life, one's mind and body be trained and developed in a spirit of humility; and that in critical times, one be devoted utterly to the cause of justice. -Gichin Funakoshi

                  Comment


                  • #10
                    Hi Bern ...

                    It's in the original post but difficult to see.. So here it is

                    'void FAR PASCAL (TALConvFreeData( TALConvData* pData );


                    Jim


                    ------------------
                    Jim..
                    [email protected]
                    Jim..

                    Comment


                    • #11
                      Hi Scott ..

                      The dwConv is a DWORD handle to the conversation with the servers
                      in Chicago. It just tells TALConvGetData which conversation to
                      use to retrieve data from.. You can have many conversations going
                      on multiple threads simultaneously...

                      Of course it ultimately gets destroyed with you are finished with
                      a conversation.. In a real world application the conversation could
                      be maintained for days, weeks, etc....



                      ------------------
                      Jim..
                      [email protected]
                      Jim..

                      Comment


                      • #12
                        Jim,

                        Just e-mail the source plus any headers revelant to the
                        project:

                        [email protected]

                        I'll take a look and reply as soon as possible!!!

                        Cheers,
                        Cecil

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

                        Comment


                        • #13
                          Jim,
                          Is it possible TALConvFreeData is just freeing the strings and it's your
                          responsibility to free the mem allocated for the udt??

                          James


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

                          Comment


                          • #14
                            Hi J.C...

                            Not really.. You don't in all cases have string data involved.. but
                            I have cleaned up any and every variable.. Null'em , Zeroed 'em,
                            shot 'em with a 357.. Even thought about drowning them in the pool.
                            The code snippet above is exactly as the "C" example.. I compiled
                            the "C" code and it runs fine.. My translation does not. When I run
                            the PB version.. The Task Manager constantly grows by 4 bytes..
                            After about an hour.. The Task Manager is showing over 32 meg and
                            growing. The "C" version sits tight at 4120k...

                            From their help files:

                            CTALConvData* TALConvGetData( DWORD dwConv )
                            Whenever any message is returned from the server, the message
                            parameters are packaged into a structure of type CTALConvData
                            and put into a special queue associated with the conversation.
                            You can then retrieve the messages one at a time by calling this
                            function. Messages are returned as a CTALConvData structure.
                            Messages returned from TALConvGetData must be released by
                            calling TALConvFreeData. The structure TALConvData looks like
                            this:

                            typedef struct
                            {
                            int iType;
                            const char* szItem;
                            LPVOID lpData;
                            DWORD dwDataLen;
                            const char* szDataFormat;
                            } TALConvData;

                            ''''

                            void FAR PASCAL TALConvFreeData( TALConvData* pData )

                            Use this function to free data messages returned from
                            TALConvGetData.



                            ------------------
                            Jim..
                            [email protected]
                            Jim..

                            Comment


                            • #15
                              Jim,
                              Try using plain DWORDS for all the udt items except the iType and assign
                              them to LOCAL variables???

                              James


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


                              [This message has been edited by jcfuller (edited May 29, 2001).]

                              Comment


                              • #16
                                Jim, the original program sure looks ok to me. The only thing I'd suggest is
                                to try updating from the CALL syntax, so:
                                Code:
                                    CALL TALConvFreeData(pData)
                                ...becomes:
                                Code:
                                    TALConvFreeData pData  ' Note: NO PARENTHESES!!!
                                The CALL syntax predates DECLAREs and, in some BASICs, does not function
                                identically to modern calling conventions. As far as I know, this is not
                                an issue with PowerBASIC, but it's the only thing I see that looks marginal.

                                The fact that the data is getting zeroed seems to suggest that it's actually
                                working, though... and the translations look fine... so it may be that you're
                                not looking in the right place.

                                ------------------
                                Tom Hanlin
                                PowerBASIC Staff

                                Comment


                                • #17

                                  James..

                                  I tried your suggestion using the DWORD with no change..
                                  Thanks..

                                  Tom..

                                  I've used/tried both with and without the CALL.. Makes no difference.
                                  One on the statements I made in the earlier post was that the task
                                  manager was increasing by 4 bytes. I was in error, it is increasing by
                                  4,000 bytes. In testing, I found that to make 250 request for data from
                                  the server increases memory by 208,000 bytes making it an average
                                  of approx. 800 bytes per request. The function is obviously suppose
                                  to retrieve a 4 byte pointer. The pointer is to a UDT that is 20
                                  bytes long. One of the members of the UDT is a pointer to ASCII data
                                  which averages 80 bytes. All of the data is correctly returned from
                                  the function but for some reason it seems as though I'm getting just
                                  a "few" more bytes from somewhere and they are not being freed..The
                                  call to TALConvFreeData is clearing the data from the UDT. It may
                                  even be cleaning up the memory on the UDT pointer correctly but it
                                  seems that there is a mysterious memory leak somewhere...

                                  Looks like I need to brush up on my "C" and port the code to a C-DLL.

                                  Many thanks to all that tried to help... and especially Cecil Williams
                                  who poured through a lot of code for me to try and find any errors..

                                  Best Regards,

                                  ------------------
                                  Jim..
                                  [email protected]
                                  Jim..

                                  Comment


                                  • #18
                                    Jim,


                                    Code:
                                        DO
                                          lReturn = TALConvWaitForData( dwConv, 250 )
                                          pData = TALConvGetData( dwConv )    
                                          SLEEP 5        
                                        LOOP WHILE( pData = %NULL )
                                    Maybe it's because you are calling TALConvGetData even if there's no data to get.
                                    Could you try putting an IF statement around it like this perhaps:

                                    Code:
                                        DO
                                          IF TALConvWaitForData( dwConv, 250 ) THEN
                                            pData = TALConvGetData( dwConv )    
                                            IF pData THEN EXIT DO
                                          ELSE
                                            SLEEP 5        
                                          END IF
                                        LOOP
                                    Tried to post this earlier, I hope my connection stays alive this time.

                                    Peter.


                                    ------------------
                                    [email protected]
                                    [email protected]

                                    Comment

                                    Working...
                                    X