Subject Problems writing/running FreePascal UDF on Firebird Linux/Windows
Author reinier_olislagers
Sorry if this is slightly OT, I'd be happy to move this to a dedicated
FreePascal list, but perhaps you've got some suggestions straightaway.

I'm trying to write a UDF that converts dotted IP address (e.g.
192.168.0.1) to integers, preferably unsigned integers.

So far, I've been able to write a FreePascal .dll/.so that seems to
work if called from a FreePascal test program.
I've tried using it as a UDF on Linux and Windows and ran into these
problems:

1. On linux, at the moment, fb cannot find the IPString2Long function.
Error:
// Engine Code : 335544343
// Engine Message :
// invalid request BLR at offset 60
// function IPSTRING2LONG is not defined
// module name or entrypoint could not be found
Windows fb 2.0 embedded does work.
2. IPLong2String at the moment, this function always returns the same
spurious value for any input given to it.

Environment:
Windows XP, Firebird embedded 2.0.1.12855, Free Pascal Compiler
version 2.2.1 [2007/10/08] for i386
Ubuntu 7.10, 2.6.22-generic, Firebird , Free Pascal Compiler version
2.2.0 [2007/08/31] for i386

Any tips (apart from rewriting in C which I probably should have done
in the first place)? I'm probably doing something wrong with the
malloc memory allocation for IPLong2String...
Please find the source code below, as well as the SQL declarations.
Thanks,
Reinier

{$IFDEF FPC}
// Compiler constants for the FreePascal compiler.
{$MODE OBJFPC} //Needed for the Result := construct
{$SMARTLINK ON}
{$IFDEF WINDOWS}
// DLL version number:
{$VERSION 0.1}
{$ENDIF}
{$ENDIF}

library ipstringconvert;

{$IFDEF FPC}
uses classes, strings, sysutils;
{$ENDIF}

{$IFDEF WINDOWS}
function ib_util_malloc(l: integer): pointer; cdecl; external
'ib_util.dll';
{$ELSE} //assume linux or unix
function ib_util_malloc(l: integer): pointer; cdecl; external
'libib_util.so';
{$ENDIF}

function IPString2Long(IPAddress: PChar): LongWord; cdecl; export;
// longword=4 bytes, unsigned.
var
parts: TStringList;
begin
parts := TStringList.Create;
ExtractStrings(['.'], [], IPAddress, parts);
// maybe rewrite using shl??
if parts.Count = 4 then
begin
Result :=
StrToInt(parts[0]) shl 24 +
StrToInt(parts[1]) shl 16 +
StrToInt(parts[2]) shl 8 +
StrToInt(parts[3])
;
{$IFDEF DEBUGOUTPUT}
write ('IPString2Long: our output will be: ' );
writeln (Result);
{$ENDIF}
end
else
begin
{$IFDEF DEBUGOUTPUT}
writeln ('IPString2Long: invalid address or something - returning 0.');
{$ENDIF}
Result := 0 ;
end;
end;

function IPLong2String(IPLong: LongWord): PChar; cdecl; export;
var
intermediate: String;
begin
intermediate := IntToStr((IPLong shr 24)and $FF) + '.' +
IntToStr((IPLong shr 16) and $FF) + '.' +
IntToStr((IPLong shr 8) and $FF) + '.' +
IntToStr(IPLong and $FF);
{$IFDEF DEBUGOUTPUT}
writeln ('IPLong2String: intermediate: ' + intermediate );
{$ENDIF}
// works but doesn't use firebird's memory allocation so use in
firebird will fail:
//Result:=StrAlloc(Length(intermediate)+1); //Allow for null
character termination
Result:=ib_util_malloc(Length(intermediate)+1);
// Use firebird's memory allocation, so it can clean up afterwards
// if function is declared in firebird using free_it
StrPCopy (Result, intermediate);
end;

exports
IPString2Long,
IPLong2String;

// This dynamic link library needs no initialisation
begin
end.