Announcement

Collapse
No announcement yet.

Calling a FUNCTION with a TYPE in the agrgument

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

  • Tom Hanlin
    replied
    If im going to declare the memory as global, why dont I just
    make a GLOBAL array of the UDT?
    I hope there's no confusion of "global data" with GLOBAL arrays, here.
    It's useful to avoid using GLOBAL variables in your program for several
    reasons. Avoiding GLOBALs means your code is more modular, which makes
    it easier to maintain and to reuse for other purposes. It also helps
    avoid confusion in cases where you might have a LOCAL variable by the
    same name as a GLOBAL variable. Plus, you don't have to wonder about
    where a variable comes from: it's either LOCAL or passed to you as a
    parameter to your SUB or FUNCTION. Plus, you're much less likely to
    run into problems with multi-threaded or callback operations.

    When you allocate global data and assign it to a pointer in a LOCAL
    array, you get the usual benefits of LOCAL values, but are assured
    that the data will persist until you're ready to deallocate it or, at
    least, until the LOCAL value goes out of scope: you do need to free
    up the memory before the LOCAL array is automatically freed by the
    compiler.

    However, it all depends on what you have in mind. This may well be
    overly complicated or otherwise inappropriate for your purposes.

    TYPE foo ' Where did foo come from???
    "Foo" (from "foobar") is one of a list of common names used by
    programmers as generic names. In this case, I might've been better off
    choosing a more meaningful name, such as MYFILEINFO.


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

    Leave a comment:


  • Lance Edmonds
    replied
    The key to using pointers is that there has to be a target and the target has to be "valid" for the pointer to use usable.

    Returning a pointer to LOCAL data (from a sub/function) is not going to work since the LOCAL data memory will be deallocated when the sub/function ends.

    However, you can certainly return a pointer to GLOBAL and STATIC data, and also if the calling code "owns" the data. ie, allocate a memory block (or string, or,...) in the calling code and pass it that to a sub/function by reference. When the target sub/function ends, the calling code still owns the data, and the data is still in "in scope".

    In summary, declaring a GLOBAL UDT is fine (and using a pointer to it in the code), as the data will still be "in-scope" in both the calling code and any sub/functions that are called.

    However, since the data is GLOBAL, using a pointer may be of little benefit anyway, since you can reference the GLOBAL UDT directly anyway.


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

    Leave a comment:


  • Mike Trader
    replied
    Tom,

    If im going to declare the memory as global, why dont I just
    make a GLOBAL array of the UDT?

    TYPE foo ' Where did foo come from???
    FileSpec AS STRING * %MAX_PATH
    FileSize AS LONG
    FileData AS BYTE PTR
    END TYPE

    GLOBAL UzData() as foo

    I thought the point was to get away from globals by somehow using
    a BYTE PTR. I think I misunderstood. It doesnt seem like
    I can use PTR here.
    (As you can tell Im a little shaky on Pointers)

    ------------------
    Kind Regards
    Mike

    Leave a comment:


  • Tom Hanlin
    replied
    Docs for UBB codes can be found here: http://www.powerbasic.com/support/forums/ubbcode.html
    (or click on the "faq" link in the upper right when reading forum messages).

    There is no problem with allocating data so that it remains valid outside the function. You
    just need to make sure it's allocated as global memory... say, using a Windows API call like
    GlobalAlloc or HeapAlloc. The data will stick around until you explicitly free it or the
    program ends.

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

    Leave a comment:


  • Mike Trader
    replied
    Michael,
    the last dimension only. I did not know that! I have only been
    testing with archives containing 4 files so far!

    Can you make a STATIC STRING array? I dont think so.

    Tom,
    I understand what you are saying.
    The part I am confused about is:
    > The data won't be destroyed if you pass it back from your FUNCTION
    (i dont know how to make the two quote lines you guys do)

    If my UDT passes a BYTE PTR back and then the function Ends (destroying
    or "abandoning" the File data that the PTR points to, what use is
    the pointer?

    Dont I have to pass the data itself back to the calling function?

    ------------------
    Kind Regards
    Mike

    Leave a comment:


  • Tom Hanlin
    replied
    Mike, the idea for the UDT is, you can use an array of type "foo",
    where each element contains (or points to) all of the information
    for a single extracted file. The reason for using BYTE PTR instead
    of STRING for FileData is so that you can have a UDT: UDTs must be
    of a fixed length.

    The data won't be destroyed if you pass it back from your FUNCTION
    or SUB. This is a more flexible technique than using GLOBAL values,
    but you're the one who best knows your requirements. If GLOBAL suits,
    use it.

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

    Leave a comment:


  • Michael Mattias
    replied
    IF Count > UBOUND(FileAndData(1)) THEN REDIM PRESERVE FileAndData(Count+4, 3)
    This should not have worked for you. The PRESERVE option of REDIM only allows you to change the last subscript of a multi-dimension array..

    As far as data being destroyed (although, 'abandoned' might be the more accurate term), if data are local, they are gone when the procedure terminates and pointers to it are no longer valid. STATIC and GLOBAL data live.

    MCM


    Leave a comment:


  • Mike Trader
    replied
    oooook if we giong to get into code then here is
    what I got working so far using a 2 dimensional array:

    Code:
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ 
    FUNCTION UnpackZip( PathAndFile AS STRING, SaveFlag AS LONG, FileAndData() AS STRING ) AS LONG
     
    LOCAL StrLen   AS LONG,   RetVal AS LONG, ZippedFile AS LONG, UzFileLen AS LONG
    LOCAL hFile    AS DWORD
    LOCAL aStr     AS STRING, UzFileStr AS STRING, TempStr AS STRING
    LOCAL zZipFile AS ASCIIZ * 260, zFileName AS ASCIIZ * 260 'or %MAX_PATH if you #INCLUDE "WIN32API.INC" 
    LOCAL global_info AS unz_global_info_s, zipfi AS zip_fileinfo_s
     
        REDIM FileAndData(4, 3) ' dimension fo 4 files to start with
        FUNCTION = 0
        zZipFile = PathAndFile
        hFile    = unzOpen(zZipFile)
        IF ISFALSE hFile THEN MSGBOX zZipFile,,"Bad Zip File" : EXIT FUNCTION
     
        RetVal   = unzGetGlobalInfo(hFile, global_info)
        IF RetVal THEN MSGBOX "Zip Archive bad, Fail #" + FORMAT$(RetVal) : EXIT FUNCTION
     
        Count    = 0
        RetVal   = unzGoToFirstFile(hFile)' get first file handle
        DIALOG SEND hDlgProgBar, %PROGBARID, 0, 0 ' Reset Progress bar
        ProgBarClr 255,153,000,  005,005,005 ' Zip-Icon-Orange On Black
        FOR ZippedFile = 1 TO global_info.number_entry 
            IF RetVal THEN RetVal = unzGoToNextFile(hFile) : MSGBOX "Can't get a Handle",,zZipFile : ITERATE ' Try next file
            UzFileLen = UnZipFile(hFile, zFileName, UzFileStr )
            IF UzFileLen THEN ' Success, file was unzipped
                INCR Count
                IF Count > UBOUND(FileAndData(1)) THEN REDIM PRESERVE FileAndData(Count+4, 3)
                FileAndData(Count, 1) = zFileName           ' Name of Archived file
                FileAndData(Count, 2) = FORMAT$(UzFileLen)  ' Length of UnZipped File
                FileAndData(Count, 3) = UzFileStr           ' The complete UnZipped file
                IF SaveFlag THEN CALL SaveFile( zFileName, UzFileStr )
            END IF
            RetVal = unzGoToNextFile(hFile) ' get next file handle
            DIALOG SEND hDlgProgBar, %PROGBARID, ROUND(ZippedFile/global_info.number_entry *100 ,0), 0 ' update progress bar
        NEXT ZippedFile
        CALL unzClose(hFile)
        REDIM PRESERVE FileAndData(Count, 3) ' Make the array size the right size
        FUNCTION = Count ' number of files succesfully unzipped
     
    END FUNCTION
     
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ 
    
    FUNCTION PBMAIN()
    '
    '
    '
        DO WHILE FileNum < UBOUND(DropFiles) AND Done = 0
            INCR FileNum
            Seperate DropFiles(FileNum), DropFo, DropFi ' Extract Path and Name
           '================================  
     
     
            IF PARSE$(UCASE$(DropFi), ".", 2) = "ZIP" THEN ' TnS files
                NumTnSZip = UnpackZip( DropFo+DropFi, 0, TnSFiles() ) ' unzip the archive, find number of files
            ELSE
                ' read the file into VbTFiles(1, 3)
            END IF 
           '================================  
     
     
            FOR i = 1 TO NumTnSZip ' Process the file(s)
                NumCtr  = ProcessVbT( VAL(VbTFiles(i, 2)),  VbTFiles(i, 3) ) ' Send: file length and the File to a function
                NumCtr  = ProcessTnS( VAL(TnSFiles(i, 2)),  TnSFiles(i, 3) ) ' Send: file length and the File to a function
            NEXT 
           '================================ 
     
        WEND ' Run thru all the dropped files 
    '
    '
    '
    END FUNCTION

    So If I just get a pointer back from the unzipping function then
    wont the actual data be destroyed when the function ends?


    ------------------
    Kind Regards
    Mike

    Leave a comment:


  • Michael Mattias
    replied
    You can pass an ARRAY of types, and REDIM the array to fit as needed

    Here is some crude code:

    Code:
    TYPE ZipFileType
     szFileName AS ASCIIZ * %MAX_PATH
     Filesize   AS LONG
    END TYPE
    
    FUNCTION WinMain yadda yadda
      LOCAL szZipFileName AS ASCIIZ * %MAX_PATH
      REDIM ZF(0) AS ZipFileType
      CALL UnZipMe (szZipFileName, ZF())
    
      FOR I = 1 to UBOUND(ZF,1)
        ProcessUnzippedFile ZF(I)
      NEXT
    
    END FUNCTION
    
    FUNCTION UnzipMe (szFile AS ASCIIZ * %MAX_PATH,ZF() AS ZipFileType) AS LONG
    
       NumZippedFiles = Somefunction(szFile)
       REDIM zf (NumZippedFiles)
       FOR I = 1 TO NumZIppedFiles
         ZF(i).szFileName = somefunction
         ZF(I).Filesize = someotherfunction
       NEXT
    END FUNCTION
    If you can't get the number of zipped files in the archive without extracting, take a look at REDIM PRESERVE to resize the array.

    MCM


    Leave a comment:


  • Mike Trader
    replied
    Thx Tom,

    But isnt a STRING passed BYREF as default?
    Thats a pointer anyway isnt it?


    And what If the Unzip function generates 4 unzipped files?
    I would have to have 4 STRINGs in that function each holding
    an unzipped file that the pointer points to right?

    I guess i could do this with a STRING array,
    but once the function ENDs the array would be destroyed, so
    the array would have to be GLOBAL in which case why even bother
    with a pointer?

    ------------------
    Kind Regards
    Mike

    [This message has been edited by Mike Trader (edited August 13, 2001).]

    Leave a comment:


  • Tom Hanlin
    replied
    Don't pass "unzipped file" as a STRING -- pass a pointer to the data.
    Then you can use a type something like this:
    Code:
    TYPE foo
      FileSpec AS STRING * %MAX_PATH
      FileSize AS LONG
      FileData AS BYTE PTR
    END TYPE
    ------------------
    Tom Hanlin
    PowerBASIC Staff

    Leave a comment:


  • Mike Trader
    started a topic Calling a FUNCTION with a TYPE in the agrgument

    Calling a FUNCTION with a TYPE in the agrgument

    I want to call my Unzip function with 2 arguments,
    NumFiles = ExtractFiles( ArchivePathAndName, Files() )

    ArchivePathAndName AS STRING * 260 ' no problem

    The Array: Files() is used to return 3 things for
    each file unzipped from the .ZIP archive

    1 - the FilePathAndName AS STRING * 260 of the unzipped file
    2 - The Length of the file AS LONG of the unzipped file
    3 - the unzipped File AS STRING

    So I cant use a TYPE cos the File could be any length
    (typically about 1MB) but that is what I need to hold the
    different data types.

    Can yuo pass a TYPE to a function anyway?

    How would you experts handle this?


    ------------------
    Kind Regards
    Mike
Working...
X