Solved

String class internal structure

Posted on 1998-12-20
22
319 Views
Last Modified: 2010-04-04
I want to build a Delphi string class in C, and then send it to a Delphi DLL. I also want to be able to read returned strings. How can this be done? - What is the internal structure of the Delphi string class?
0
Comment
Question by:obg
  • 7
  • 6
  • 4
  • +2
22 Comments
 
LVL 4

Expert Comment

by:dwwang
ID: 1352194
You don't need to do that, you can use C strings, in Delphi, it is called Pchar. You can manipulate them in Delphi DLLs and return them. In Delphi, there are many functions can process NULL terminated strings, all begin with "str", such as strCopy,...

Need any further information, drop me a comment.
0
 
LVL 2

Author Comment

by:obg
ID: 1352195
Sorry. I don't have the DLL source. I know it's "bad manners" to use other types of strings in Win32 environment than Pchar, c-type, but it's not within my control.

0
 
LVL 10

Expert Comment

by:viktornet
ID: 1352196
Hello there...

I think that dwwang's answer was correct.... I have no idea why you rejected it, but anyway... here is a more detailed explanation...

in C you'd declare the strings like this...

char *str = "Whatever";  //or
char str[100];

This in Delphi would be declared like so...
var
  str : PChar;

then you can pass the C str to the Delphi str...

here is an example...

C function...

char *foo(char *str)
{
  return str;
}

In Delphi you could do the following in order to receive the string,..

var
  pStr : PChar;
  Str : string;
begin
  pStr := foo('whatever');
  str := strpas(pStr); //Now you have an original STRING type variable...
  ShowMessage(str);
end;

Hope this helps...

-Viktor
--Ivanov
0
 
LVL 4

Expert Comment

by:dwwang
ID: 1352197
Hi, vik, thanks. But I understand obg's problem, he does not have the DLL source! :-)

Hi,obg: I think the problem might not be so easy, you can view system.pas in Delphi source, there is some conversion between PWideChar and string(don't know whether convertion from PChar is the same or not).

Regards,
Wang
0
 
LVL 2

Author Comment

by:obg
ID: 1352198
Thanks for your answer, viktornet, but again - I don't have the DLL source...

Thanks for the tip, dwwang. I'll have a look at my Delphi installation at work...

0
 
LVL 2

Author Comment

by:obg
ID: 1352199
Adjusted points to 300
0
 
LVL 20

Expert Comment

by:Madshi
ID: 1352200
O-oohhh. I guess, you'll have problems with what you want to do. If I understand you right, you've a Delphi dll that imports functions with Delphi strings as parameter, right?
In such cases Borland/Inprise claims, that you import the unit ShareMem in both the dll and the program that uses the dll. The unit ShareMem does the following: Delphi strings are automatically allocated/deallocated by Delphi's memory manager. Your program would probably crash, if Delphi tries to handle a string that is allocated from another memory manager. So the unit ShareMem makes sure that both the program and the dll use the same memory manager.
If you want to write a C program that allocated Delphi strings and give these strings to a Delphi dll, you'll have to use the same memory manager in C that the Delphi dll uses.
Hmmm, did you understand this? Any questions?
Or did I misunderstand your problem?

Regards, Madshi.
0
 
LVL 20

Expert Comment

by:Madshi
ID: 1352201
Of course I mean a Delphi dll that EXPORTS functions width Delphi strings as parameter...
0
 
LVL 4

Expert Comment

by:dwwang
ID: 1352202
Madshi's comment sounds reasonable, anyway, you can find what you want the descriptions in Delphi's help, see the topic of "Long string types", it describes how a string is internally stored in memory.
0
 
LVL 20

Expert Comment

by:Madshi
ID: 1352203
Hmmm. In "system.pas" you'll find this declaration:

type
  StrRec = record
             allocSiz: Longint;
             refCnt:   Longint;
             length:   Longint;
           end;

This record is stored in front of the string data itself. So a string "test" would probably allocated with the length of 12+4=16 bytes, where the allocSiz and the length would be set to 4 and the refCnt to 1.

But as you can read in my last comment, I think you'll get problems if you just allocate this string structure in your C program, since the Delphi dll needs the string to be allocated by it's own memory manager...

Regards... Madshi.
0
 
LVL 2

Author Comment

by:obg
ID: 1352204
Gee... Lots of comments. - Thanks!

Ok. What is refCnt? - The number of references, for garbadge collect...? What if I can settle with reading returned strings, whould that be possible? Would not allocSiz be set to 16 (or maybe more) in the example above?
0
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 
LVL 1

Accepted Solution

by:
hustch earned 300 total points
ID: 1352205
A Delphi string (long string) is a pointer, which is used in the following way:

When the pointer is nil (null), the string is empty.
Otherwise, the pointer holds the address of the string data :

  32-bit   : Refererence count
  32-bit   : Length
  1-x byte : String data, zero terminated.

The reference count is used by Delphi for deallocating memory. Delphi don't copy the data unless it is nessecary. If the data is changed when the reference count is > 0, the data is copied to a new location before they are changed.
When a string variable goes out of scope (or is assigned a new value), it is decreased. When it reaches zero, the memory is deallocated.
If you don't use it, you should just set it to one, to prevent Delphi to attempt to deallocate it.

The Length field is the length of the data, not counting the zero at the end of the data.

The actual string data has the same format as a PChar. When you typecast a string to a PChar, Delphi simply gives you the address of the data-part. That is why, you can normally use string variables, where PChar parameters are required. This makes it easy to pass string data to non-Delphi functions, like the Win32 api.
0
 
LVL 2

Author Comment

by:obg
ID: 1352206
Thanks for your answer, hustch, but what about allocSiz? Otherwise it was almost the same explanation as Madshi gave me, apart from the zero termination.
0
 
LVL 20

Expert Comment

by:Madshi
ID: 1352207
Grfpgfpffgd##dfgg#@$§&$, you're right, it was almost the same explanation as mine. So why (dam...) give you the points to him and not to me????????
And you should always test answers before accepting them! As I said before: I think you'll get problems with the memory manager...
0
 
LVL 1

Expert Comment

by:hustch
ID: 1352208
The allocSiz is for Delphi memory administration, which is quite complex. It looks as if Delphi allocates mery in 4-byte bloks, and it uses different strategies for bloks smaller than 4kb, than for larger blocks.
Do you need to deallocate strings allocated in the dll ?
parameters, If you only passes input you don't.

By the way, I did a little test, and the pointer value, that Delphi passes for parameters is the address of the 1st character in the string, not the address of any of the preceding fields.
0
 
LVL 2

Author Comment

by:obg
ID: 1352209
First of all: I am so sorry Madshi, but he posted it as an answer, and you did not. I was also tired of rejecting peoples answers, as I think that I know most of what I have to know. I think that this might take to much work, for which my client can't pay... Again I'm sorry, but be pissed at him - not me.

Hustch: I probably ought to deallocate the strings. Or maybe not... Don't they get free'd when I do FreeLibrary?
0
 
LVL 20

Expert Comment

by:Madshi
ID: 1352210
obg, I didn't post an answer because Wang and Viktor already helped you. So I chose the polite way and wanted to give you the possibility to decide which comment helped you the most. Unfortunately I often get punished for this kind of politeness...     :-(
However, I can't buy something with the points, so forget it...
0
 
LVL 1

Expert Comment

by:hustch
ID: 1352211
FreeLibrary doesn't free allocated memory, because it belongs to application, not the dll. A dll and the exe shares memory, and when a dll is used by more than one application, only the code is shared, so if the dll has a global variable, it has a copy for each process that uses the dll.

If the amount of lost memory (or number of lost memory-blocks) is acceptable, you can ignore it, it will be free'd when the application terminates.
Otherwise, if you have Deplhi at work, you could create a small dll, with a function for allocation, and one for deallocation.

To Madshi:
I think most of your answer is inaccurate, and while correct in some situations, it is plain wrong in other situations. If you knew that, you should have written someting about it.
0
 
LVL 20

Expert Comment

by:Madshi
ID: 1352212
hustch,

don't think my answer is inaccurate. What are you talking of? Ok, if I look again at what I've written, the allocSiz is wrong, but that's surely not "most of my answer".

BTW, your idea with the second Delphi dll is nice. But it should be added that obg has to import the unit ShareMem. It seems that you totally ignore the memory manager problems...

Regards... Madshi.
0
 
LVL 1

Expert Comment

by:hustch
ID: 1352213
Madshi.

You also says, that "the Delphi dll needs the string to be allocated by it's own memory manager". That is only true, if it tries to deallocate it, which I have described how to avoid.

The ShareMem issues has already beed described (by you I think).

Grüße
0
 
LVL 10

Expert Comment

by:viktornet
ID: 1352214
Hey guys...

Doesn't the word "Grüße" w/o the quotes means not polite or something?

btw- No need to fight anyway. It's Christmas y'all, but if i need to take a side i agree with Madshi mostly... Most of the time there is no such a thing as right answer.. There are many ways to accomplish things so chill out y'all...

-Viktor
--Ivanov
0
 
LVL 20

Expert Comment

by:Madshi
ID: 1352215
Hi Viktor, thanx for your support...  :-)

"Grüße" is just the german word for "Regards".

hustch, the problem is, that we don't know, what the Delphi dll does with the strings. Perhaps one function takes a "var string" as a parameter and internally tries to empty/change the string and then you can't avoid that the dll tries to deallocate/reallocate the string. However with a second Delphi dll obg should be able to solve this allocation problem.

Regards/Grüße, Madshi.
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Suggested Solutions

In this tutorial I will show you how to use the Windows Speech API in Delphi. I will only cover basic functions such as text to speech and controlling the speed of the speech. SAPI Installation First you need to install the SAPI type library, th…
Introduction I have seen many questions in this Delphi topic area where queries in threads are needed or suggested. I know bumped into a similar need. This article will address some of the concepts when dealing with a multithreaded delphi database…
Illustrator's Shape Builder tool will let you combine shapes visually and interactively. This video shows the Mac version, but the tool works the same way in Windows. To follow along with this video, you can draw your own shapes or download the file…
When you create an app prototype with Adobe XD, you can insert system screens -- sharing or Control Center, for example -- with just a few clicks. This video shows you how. You can take the full course on Experts Exchange at http://bit.ly/XDcourse.

705 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now