We are testing with a third party dll within the Powerbuilder development environment

passing variables to the dll functions and receiving variable values back.  Everything works fine except for the return of string variable values which are mostly non letter characters.  
Function declaration with the problem:
int tixGetRecordA(TCursorHandle Cursor, const char **RecordID, const char **RecordData, const char **FoundTerms, int *Precision, int *Score, WORD CodePage); 
Powerbuilder external function declarations for the variables in order are set as follows uLong Cursor, Ref String RecordID, Ref String RecordData, Ref String FoundTerms, Ref Integer Precision, Ref Integer Score, uInt codePage.
Proper values are being returned except for the String variables?  Wondering what could be causing the issue?

Open in new window

Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

And what is the code of the function in question?
peachkjAuthor Commented:
The third party dll is for full text indexing of a database column.  Documentation is in the attached MSWord function where the string values are not returning correctly is tixGetRecordA in the tixProcessQuery section at the end of the document.
peachkjAuthor Commented:
Specification for third party function tixGetRecordA where we are not succeeding in having proper strings returned.
Cloud Class® Course: Amazon Web Services - Basic

Are you thinking about creating an Amazon Web Services account for your business? Not sure where to start? In this course you’ll get an overview of the history of AWS and take a tour of their user interface.

As you are passing string arguments by reference to external functions (any dlls or database stored procedures) you may need to allocate memory to those variables before calling function. FYI...Memory allocation is not required for other datatypes when you pass by reference.

See example in code snippet. Hope this will work for you...

Function declaration
int tixGetRecordA(uLong Cursor, Ref String RecordID, Ref String RecordData, Ref String FoundTerms, Ref Integer Precision, Ref Integer Score, uInt codePage); 
Clicked Event of button
string ls_recordid,ls_recorddata,ls_foundterms
integer li_return
//suppose max return length of ls_recordid,ls_recorddata,ls_foundterms are 10,1000& 100 respectively. Then assign memory as below
ls_recordid = space(10)
ls_recorddata = space(1000)
ls_foundterms = space(100)
//now call function
li_return = tixGetRecordA(.....all arguments......)

Open in new window

peachkjAuthor Commented:
I have done the memory allocation as you've indicated, however this has not worked.  In the function declaration (int tixGetRecordA(TCursorHandle Cursor, const char **RecordID, const char **RecordData, const char **FoundTerms, int *Precision, int *Score, WORD CodePage) there are double asterisks ** on the Char variables (RecordID, RecordData, and FoundTerms) that are providing the problem.  Checking some C++ documentation these double ** inidicate a pointer to a pointer pointing to a variable location.  So the question now becomes how does Powerbuilder handle this? if in fact this is the issue?
according to me it should be handled with by reference only. Make sure that you have assigned the same memory that function is supposed to return. Or if you can know how to call this function from VB it may help.
one more thing...in PB 10 and later versions you have to put keyword ';ansi' with external function declaration if you have any string variable as reference argument.

{ access } FUNCTION returndatatype name ( { { REF } datatype1 arg1,
    ..., { REF } datatypen argn } ) LIBRARY "libname"
    ALIAS FOR "extname{;ansi}"

Don't remember whether it was there in pb6.5 or not?
peachkjAuthor Commented:
I've checked PB6.5 documentation and the "ansi" ALIAS option is not documented.  Changed code and when the program was run received an error message concerning the "ansi" option.  So this is not an option for this version.   So we're still looking.

No sure of what you mean by your comment: "Make sure that you have assigned the same memory that function is supposed to return. "

 Considering upgrading PB.
"Make sure that you have assigned the same memory that function is supposed to return. " - it means if function tixGetRecordA returns/assigns 1250 characters to reference variable then before passing that variable you have to assign that much memory.

ls_recorddata = space(1250)

In my previous post space(1000) was just for example you have to put the exact or more memory that i believe.
In 32-bit world PowerBuilder can only call external functions that have used the standard calling sequence (pascal calling sequence for 16-bit) - check the third party DLL

peachkjAuthor Commented:
We've significantly increased the amount of each ** variable but this does not resolve the issue.  As well, have tested it under PB 10.5 at an associated company with the  "ALIAS FOR "extname{;ansi}"
included in the declaration of the of the PB external function, again with no success.  Because all other variables are being returned successfully, we believe that it is an issue with how PB deals with the double ** pointer pointing to another pointer pointing to the stored value.   Is there a PB function to use with the pointer memory value to reference the stored values?  Hope that makes sense.
peachkjAuthor Commented:
Solution determined:

Local function declaration:
Function Integer tixGetRecordA(Long l_Cursor, Ref Long l_RecID, Ref Long l_RecData, Ref Long l_Found, Ref Integer i_Precision, Ref Integer i_Score, Int i_CdPg) LIBRARY "tix.dll"

Code in script:
li_Result = tixGetRecordA(ll_Cursor, ll_RecordID, ll_RecordData, ll_FoundTerms, li_Precision, li_Score, li_CodePage)
Use the PB String with the keyword "ADDRESS"  and a local variable as follows
            ls_RecordIDPt = String(ll_RecordID, "ADDRESS")            
            ls_RecordID = ls_RecordIDPt

ls_RecordID provides the desired information.

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Force accepted.
Community Support Moderator
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Editors IDEs

From novice to tech pro — start learning today.