wezelboy Posted June 21, 2007 Share Posted June 21, 2007 Has anyone else had a problem using a dynarray of char as a variable parameter in a user defined function? What I am seeing in my script is the contents of the array disappear as soon as the procedure returns. If I change the type of the variable parameters to STRING, it works just fine. Scoping the function inside the calling function doesn't help, and I don't think it is an ALLOCATE problem because the dynarrays hold values just fine inside the function. Here's the function followed by the function that is calling it FWIW... (Sorry about the lack of tabbing...) {************************************************************} FUNCTION LibHasIDLabel(theObj: HANDLE; VAR theRecordName, theIDLabel: DYNARRAY[] OF CHAR): BOOLEAN; VAR recHand: HANDLE; recIndex, fieldIndex: INTEGER; recName, fieldName: STRING; labelFound: BOOLEAN; BEGIN LibHasIDLabel := FALSE; labelFound := FALSE; recIndex := 1; WHILE ((recIndex <= NumRecords(theObj)) AND (NOT labelFound)) DO BEGIN recHand:= GetRecord(theObj, recIndex); recName:= GetName(recHand); fieldIndex := 1; WHILE ((fieldIndex <= NumFields(recHand)) AND (NOT labelFound)) DO BEGIN fieldName := GetFldName(recHand, fieldIndex); IF ((Pos('IDLabel', fieldName)) = 1) THEN BEGIN theRecordName := recName; theIDLabel := GetRField(theObj, recName, fieldName); LibHasIDLabel := TRUE; labelFound := TRUE; {DBGINFO} Message('IDLabel ', theIDLabel, ' found in record ', theRecordName); Wait(2); {\DBGINFO} END; {IF Pos} fieldIndex := fieldIndex + 1; END; {WHILE fieldIndex} recIndex := recIndex + 1; END; {WHILE recIndex} END; {Lib_HasIDLabel} {************************************************************} FUNCTION CopyOver(theDestPIO: HANDLE): BOOLEAN; VAR parent, newObj, tempGroup: HANDLE; destPIOType, srcPIORecName, destPIORecName, srcPIOIDLabel, destPIOIDLabel: DYNARRAY[] OF CHAR; index: INTEGER; BEGIN IF (GetType(theDestPIO) = OBJ_PIO) THEN BEGIN {Make sure the two plug-ins are of the same type} destPIOType := LibGetPIOType(theDestPIO); {DBGINFO} Message('Destination PIO of type ', destPIOType, ' picked'); Wait(1); {\DBGINFO} IF (Pos(srcPIOType, destPIOType) = 1) THEN BEGIN {Copy the IDLabel of theDestPIO to the srcPIO so that it is retained} IF (LibHasIDLabel(theDestPIO, destPIORecName, destPIOIDLabel)) AND (LibHasIDLabel(srcPIO, srcPIORecName, srcPIOIDLabel)) THEN BEGIN SetRField(srcPIO, srcPIORecName, 'IDLabel', destPIOIDLabel); {DBGINFO} Message('IDLabel ', destPIOIDLabel, ' copied to source PIO Record ', srcPIORecName); Wait(3); {\DBGINFO} END; {IF LibHasIDLabel} {Strip the non PIO records from theDestPIO} index := 1; WHILE ( index < NumRecords(theDestPIO)) DO BEGIN {DBGINFO} Message('Deleting record ', index, ' from destPIO'); Wait(1); {\DBGINFO} DelObject(GetRecord(theDestPIO, index)); index := index + 1; END; {WHILE index} {Add any extra records that the srcPIO has} index := 1; WHILE ( index < NumRecords(srcPIO)) DO BEGIN {DBGINFO} Message('Copying record ', index, ' from sourcePIO'); Wait(1); {\DBGINFO} LibCopyNewRec(srcPIO, theDestPIO, GetName(GetRecord(srcPIO, index))); index := index + 1; END; {WHILE index} {Copy the PIO Record} {DBGINFO} Message('Copying the PIO Record'); Wait(1); {\DBGINFO} LibCopyExistRec(srcPIO, theDestPIO, destPIOType); {Reset the dest object so that the changes are reflected} ResetObject(theDestPIO); END; {IF Pos} END; {IF GetType} CopyOver := FALSE; END; {CopyOver} Quote Link to comment
ccroft Posted June 22, 2007 Share Posted June 22, 2007 (edited) I've never used dynarray so maybe you can teach me something. Where is ALLOCATE happening? I would've thought you'd need that in the second function after you declare them and before you assign to them. (does sound like a scope problem of some kind) edit: and while we're at it, why is dynarray of char preferable to string? Edited June 22, 2007 by ccroft Quote Link to comment
MullinRJ Posted June 22, 2007 Share Posted June 22, 2007 the contents of the array disappear as soon as the procedure returns. Do you mean when CopyOver returns, or when LibHasIDLabel returns, or the whole PIO procedure? If you mean CopyOver, I think Charles is right, it is a problem of the variables' scope. Each time you leave the function CopyOver, you should expect all your locally declared variable data to be invalid. The fact that Stings don't is an abnormality, not the norm. To get the values to stick each time you enter CopyOver, declare the following as global variables and not local: gdestPIOType, gsrcPIORecName, gdestPIORecName, gsrcPIOIDLabel, gdestPIOIDLabel: DYNARRAY[] OF CHAR; You can use the global variables locally, but I would add them to the calling chain to keep it neat and tidy, as: FUNCTION CopyOver (theDestPIO: HANDLE; VAR destPIOType, srcPIORecName, destPIORecName, srcPIOIDLabel, destPIOIDLabel: DYNARRAY[] OF CHAR): BOOLEAN; As for allocating variable space before it is used it, I always do, except when reading from files. If your first assignment allocates what you need, you should not expect to be able to add more to a text variable unless you allocate additional space for it. You can always shorten the character data, though. If your data is shorter than 255 characters, why not use Strings and forget about all the hassles of allocation. Raymond Quote Link to comment
wezelboy Posted June 22, 2007 Author Share Posted June 22, 2007 CopyOver calls LibHasIDLabel and not the other way around. The dynarrays are declared in CopyOver, and are passed to LibHasIDLabel as variable parameters. Inside LibHasIDLabel, they work fine. Quote Link to comment
MullinRJ Posted June 22, 2007 Share Posted June 22, 2007 Your function declarations are as follows: FUNCTION LibHasIDLabel(theObj: HANDLE; VAR theRecordName, theIDLabel: DYNARRAY[] OF CHAR): BOOLEAN; FUNCTION CopyOver(theDestPIO: HANDLE): BOOLEAN; And your calling line: IF (LibHasIDLabel(theDestPIO, destPIORecName, destPIOIDLabel)) AND (LibHasIDLabel(srcPIO, srcPIORecName, srcPIOIDLabel)) THEN... When your function LibHasIDLabel completes, it returns a pointer to variable space that was local to LibHasIDLabel; space that disappears the moment you leave LibHasIDLabel. The equivalent space has not been reserved in CopyOver since you never allocated it, so there's no place for the answers to reside when you return. You must ALLOCATE space for your DynArrays before they can be used. Try: ChrCnt := 94; { or whatever size your array of Chars needs to be. } ALLOCATE destPIORecName[1..ChrCnt]; ALLOCATE destPIOIDLabel[1..ChrCnt]; ALLOCATE srcPIORecName[1..ChrCnt]; ALLOCATE srcPIOIDLabel[1..ChrCnt]; IF (LibHasIDLabel(theDestPIO, destPIORecName, destPIOIDLabel)) AND (LibHasIDLabel(srcPIO, srcPIORecName, srcPIOIDLabel)) THEN... Now, when LibHasIDLabel returns, your data has something to come home to. Of course, ChrCnt can have a different value for each variable, if your needs require it. HTH, Raymond Quote Link to comment
wezelboy Posted June 22, 2007 Author Share Posted June 22, 2007 Thanks Raymond. I thought it might be something like that. -P Quote Link to comment
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.