Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations derfloh on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Fixed Length Strings 1

Status
Not open for further replies.

halveb

IS-IT--Management
Mar 28, 2004
8
US
I am calling a DLL where one of the parameters is a fixed length string (of 8000 bytes). In Visual Basic a fixed string can be dimensioned so that the string will always be of that size.

Is there a way to do this in Delphi?

I have tried using the SetLength(string, size) function but this didn't do the trick. Any help would be appreciated.

Thanks
 
SetLength just allocates the memory for the maximum length of a string, it doesn't actually make the string it references that long.

From the Delphi 5 help topic: Declaring and Initializing Strings
When you use SetLength, existing characters in the string are preserved, but the contents of any newly allocated space is undefined.

I may be wrong, but I suspect that your .dll is looking for a string that is actually 8000 characters long. You could use the StringOfChar to pad the string you're trying to pass to the .dll. Something like this (assuming that "S" is the string you want to pass to the .dll):
Code:
function GetPaddedString(s:String): String;
begin
  result := s + StringOfChar(' ', 8000-length(s));
end;

-D
 
Thanks Hilfy that explains why the SetLength didn't work. I you could be right but I tried assigning 8000 spaces to the variable I send and it didn't work. I need to find out what the VB code does with the following variable definition:

Global hllData As String * 8000

It is most definetely a fixed length string but what the 8000 represents I don't know? Thanks for the suggestion I think I am on the right track now.
 
Calling a foreign DLL function with a Delphi string is NOT advisable.

Use a memory block instead.

buho (A).
 
I did a search on Memory Block and saw a post you had written about sharing memory between applications. I haven't read it in detail yet but it looks as though you are dealing with passing pointers.

In this particular instance the DLL needs the string to be passed by value not by reference. Would a memory block still work? If so, I will dig into the response you gave regarding sharing memory between applications.

Incidentally why is it not advisable to call a foriegn DLL with a string? Is it because in Delphi you cannot control where the string is in memory?

Thanks buho.
 
The memory block approach will work. You need to pass a derreferenced pointer.

Code:
var
  P : pointer;
begin
  GetMem(P, 8000);
  Call_DLL(P^);   // Note P^.
  FreeMem;
end;

A Delphi string is not only the chars space but some control information too. If the DLL is not expecting the exact structure a Delphi string have, the DLL code can screw up the control info.

Another possible approach can be:

Code:
var
  S : AnsiString;
begin
  SetLength(S, 8000);
  Call_DLL(S[1]);  // To be sure you are passing the char space
end;

But now Delphi itself can be fooled by the string and you can not count on Length(S) after calling the DLL. Personally, I don't like this approach.

Actually, what is best and what work or not depends on the DLL. Knowing in what language the DLL is implemented can be of help.

On a side note, SetLength will create a memory block of 8000 bytes until the first time you store something in it with Delphi code. What the help is saying is that you have no idea about the content of the assigned space.

buho (A).



 
Just a random thought I had....Have you tried casting your string as a PChar when you send it to the .dll?

-D
 
In some ways PChar(S) is like S[1], as the address seen by the code points to the data space and not to the string control area.

But the whole point is: ansi strings are opaque structures; what works today can stop working in the next compiler version.

After the D5 --> D6 compatibility issues I'm not betting in Borland any more.

buho (A).

 
buho,

On a side note, SetLength will create a memory block of 8000 bytes until the first time you store something in it with Delphi code. What the help is saying is that you have no idea about the content of the assigned space.

that's why it is a good thing to do a Fillchar(buffer,' ') after the setlength call.


halveb :

on a general not, when a DLL is written in C (or C++) it is good to use pchars (#0 terminated string) since C uses this also. you must only take care to see who has the "responsablity" to reserve the memory for the pchar...


--------------------------------------
What You See Is What You Get
 
Okay I ma getting close. Using the first piece of advice I received from hilfy I was able to get the call to the DLL to work.

function utlapi(var func:LongInt; DataString:string; var Length, RetC, Xtra1, Xtra2:LongInt):LongInt; stdcall; external 'PCSUTL32.DLL';

This is my call to the DLL. This DLL is called by many different processes and it reacts differently based on primarily the first variable which defines which internal function will be called. The DLL is expecting a string for the 2nd parameter.

function utl_GetString(intRow:integer; intColumn:integer; strGetString:string; intStringLength:integer):LongInt;

begin
HllFunctionNo := UA_GET_STRING; {235}
HllData := StringOfChar(' ', 8000);
HllLength := intStringLength;
HllReturnCode := 0;
HllParm5 := intRow;
HllParm6 := intColumn;
lngTempRC := utlapi(HllFunctionNo, HllData, HllLength, HllReturnCode, HllParm5, HllParm6);
strGetString := MidStr(HllData, 1, intStringLength);
utl_GetString := HllReturnCode;
end;

The above code actually works and returns the values I expect into strGetString. I use this DLL in basic which defaults to passing parameters by reference rather than by value and thus the string I receive in strGetString never gets back to the calling function. I would think that it would be simple then to declare the strGetString parameter as var so its value is returned to the calling code but it doesn't work then?

I am confused????
 
Got it. I must have messed up memory when I did something wrong cause it is working like a charm now.

Thanks to everyone for the help and ideas.

halveb
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top