You chosen wrong datatype jokers.
String
, PChar
, and Char
are not data types in Delphi, but aliases to some actual data types.
Depending on Delphi version and sometimes on compiler settings those can be shortcuts to types such has:
- in Delphi 2009+:
UnicodeString
,PWideChar
,WideChar
- by default in pre-Unicode 32-bit Delphi:
AnsiString
,PAnsiChar
,AnsiChar
- in 16-bit Delphi or with compatibility settings:
ShortString
,PAnsiChar
,AnsiChar
So using type aliases in type-unsafe DLL project, you gambled that Delphi compiler would choose suitable data types for you. This time the bet failed.
WideChar
and UnicodeString
use UTF-16 charset, that for non-Unicode application (or for application, expecting non-Unicode data by protocol) would look as zero-interlaced strings like (in pre-2009 Delphi terms) 'a'^@'b'^@'c'^@
instead of 'abc'
. This, according to ASCIIZ (C) string convention means the string ends after the 1st character.
Hence, you should make you DLL interface match on both side: your sources and Firebird expectations.
- If possible, you may try to say Firebird that those fields and results use UTF-16 charset, but i doubt that Firebird supports it on
CSTRING
. - You can code your DLL according to Firebird DLL expectations using datatypes
AnsiString
,PAnsiChar
,AnsiChar
I also strongly suggest you reading Delphi help about Unicode in Delphi 2009+ and its implication on compatibility, especially on low-level type-unsafe things like DLLs and pointer maths. There are also few articles on topic in Google.
Using DLLs you remove type safety checks of Delphi compiler, and thus you take the responsibility of ensuring identical binary data representations on both sides of DLL APi. Type aliases like string
, char
and PChar
would make it very fragile and error prone.
Additionally i cannot see a calling convention you selected for your DLL entrypoint function. Did you marked your function with cdecl
keyword or stdcall
or register
?
Judging by c:\Program Files (x86)\Firebird\Firebird_2_1\include\ib_util.pas
cdecl convention is most probably correct one, but you should check Firebird manuals on this topic.
http://en.wikipedia.org/wiki/Calling_convention#x86
That is for 32-bit code however, for 64-bit UDFs some another convention would be probably asked for.
Now, one more strange thing is your choice of parameters' modes.
Your function has parameters like var xxx:pointer
and that means double indirection.
Your function expects pointer -> to pointer -> to character and that does not seems correct or rational.
I'd changed var
qualifier to const
in your function parameters definitions.
This sample - though it is abandoned and of questionable quality (it suffers from the mantioned above dizzy aliases problem) also supports the idea that VAR
qualifier is wrong here: http://fireudflib.cvs.sourceforge.net/viewvc/fireudflib/src/EMail.pas?view=markup
Bringing these points together, i guess your function should look like
function FormatRasaSingle(const formatRasa, aDenumire, aCod, aSimbol, aTulpina : PAnsiChar) : PAnsiChar; cdecl; export;
var tmpString : AnsiString;
tmpInteger : Integer;
begin
tmpString := 'MAMA';
Assert( SizeOf(tmpString[1]) = SizeOf(byte) );
tmpInteger := Length(tmpString);
Result := ib_util_malloc(tmpInteger + 1);
StrPLCopy(Result, tmpString, tmpInteger);
end;
http://docwiki.embarcadero.com/Libraries/XE3/en/System.SysUtils.StrPLCopy