Home Is it safe to pass Delphi const string params across memory manager boundaries?

# Is it safe to pass Delphi const string params across memory manager boundaries?

himself
1#
himself Published in 2010-07-05 10:47:50Z
 Subj. I'd like to use strings instead of PChar because that spares me much casting, but if I just do procedure SomeExternalProc(s: string); external SOMEDLL_DLL;  and then implement it in some other project with non-shared memory manager: library SeparateDll; procedure SomeExternalProc(s: string); begin //a bla bla bla //code here code here end;  I have (formally) no guarantee Delphi does not decide for whatever reason to alter the string, modify its reference counter, duplicate or unique it, or whatever else. For example var InternalString: string; procedure SomeExternalProc(s: string); begin InternalString := s; end;  Delphi increments refcounter and copies a pointer, that's it. I'd like Delphi to copy the data. Does declaring the parameter as "const" make it safe for that reason? If not, is there a way to do it? Declaring parameter as PChar doesn't seem to be a solution because you need to cast it every time: procedure SomeExternalProc(s: Pchar); forward; procedure LocalProc; var local_s: string; begin SomeExternalProc(local_s); //<<--- incompatible types: 'string' and 'PAnsiChar' end; 
Mason Wheeler
2#
Mason Wheeler Reply to 2010-07-05 12:25:43Z
 That would probably work, as long as you only ever use your DLL from code compiled in the same version of Delphi. The internal format of string has been known to change between releases, and you have no formal guarantee that it won't change again. If you want to avoid having to cast everywhere you use it, try wrapping the function, like this: procedure SomeExternalProc(s: Pchar); external dllname; procedure MyExternalProc(s: string); inline; begin SomeExternalProc(PChar(local_s)); end;  Then in your code, you call MyExternalProc instead of SomeExternalProc, and everyone's happy.
Community
3#
 If both the app and the DLL are written in the same Delphi release, just use shared memory manager (more details here). If one side is written in a different language than there's no other way but to use PChar or WideString (WideStrings are managed by the COM memory manager). Or you can write a wrapper function: procedure MyExternalProc(const s: string); begin SomeExternalProc(PChar(s)); end; 
 Just to add a single fact: Delphi allows you to simply assign PChar to a string so on the DLL side you don't need any typecast: function MyDllFunction(_s: PChar): integer; var s: string; begin s := _s; // implicit conversion to string // now work with s instead of the _s parameter end;  This also applies for passing PChar as a parameter to a function that expects a (by value) string.