Subject Re: [firebird-support] UDF:s and strings i Delphi
Author Pavel Menshchikov
Hello Kjell,

KR> I saw in an UDF intro doc for Delphi that you could cast the string
KR> input args to Delphi strings using
KR> string(ThePCharArg)
Do you mean casting inside an UDF? Something like
-----
function myUDF(InStr: PChar): PChar; cdecl; export;
var
tmpstr: String;
begin
...
tmpstr:=String(InStr);
...
end;
-----
I think there are no problems with that.

KR> I've also read that UDF:s should use FB's (IB's?) memory allocation
KR> function(s).
As I remember, it is not recommended to use borland strings as
input/output parameters or returning value because they are handled by
borland memory manager. Instead, it is recommended to use MS or FB/IB
memory manager. For example:
-----
// MS memory allocation function
function malloc(Size: Integer): Pointer; cdecl; external 'msvcrt.dll';
function myUDF(InStr: PChar): PChar; cdecl; export;
var
tmpstr: String;
begin
...
tmpstr:='some info';
...
Result:=malloc(Length(tmpstr)+1); // +1 for C str. terminator
StrPCopy(Result, tmpstr);
...
end;
-----
Note that such UDF must be declared with FREE_IT for return value in
FB database: FREE_IT indicates that the memory was allocated and FB
has to free it. Example:
-----
DECLARE EXTERNAL FUNCTION myudffunc
CSTRING(10)
RETURNS CSTRING(10) FREE_IT
ENTRY_POINT 'myUDF' MODULE_NAME 'myudfmodule';
-----

You may also use another way, which allow FB to allocate memory for
you. It is something like
-----
procedure myUDF(InStr: PChar; var OutStr: PChar); cdecl; export;
begin
// check if OutStr<>nil - then FB has allocated the memory
// processing
...
end;
-----
and
-----
DECLARE EXTERNAL FUNCTION myudffunc
CSTRING(10), CSTRING(10)
RETURNS PARAMETER 2
ENTRY_POINT 'myUDF' MODULE_NAME 'myudfmodule';
-----

Then in both cases you can call the UDF in the same manner:
-----
select myudffunc(:inparam),... from ... -- in DSQL/PSQL
-----
or
-----
retval=myudffunc(:inparam); -- in PSQL
-----

I don't use the latter way of UDF definition, so I can't tell you if I
specified all correctly.

KR> But doesn't the above string conversion allocate dynamic memory in
KR> Delphi? Will it really work?
For local variables it's ok, I think (I use it without problems in
D6).


HTH
--
Best regards,
Pavel Menshchikov
http://www.ls-software.com