Subject Re: Firebird 64 bit and UDF write in Delphi (32 bit)
Author mohamed.banaouas
> Hi,
> this seem to be problem with version of UDF.
> Pls. try this:
> STOP FB
> Copy new verison of UDF to firebird UDF directory (no more udf with same
> name in system)
> START FB
>
> Check again.
I did all of this in a command line script myudf.cmd.
and here is the output:
FUNCTION_DEFINITION
============================================================
MYINT / MYUDF.DLL / MYINT

MYINT
============
12345

FUNCTION_DEFINITION
============================================================
MYPCHAR / MYUDF.DLL / MYPCHAR

Statement failed, SQLCODE = -104
invalid request BLR at offset 63
-function MYPCHAR is not defined
-module name or entrypoint could not be found
After line 17 in file myudf.sql


here is the script myudf.cmd:
@echo off
:: myudf.cmd
::------------
set udflib=myudf
set fbroot=c:\firebird
set fbudf=%fbroot%\udf
set fbbin=%fbroot%\bin
set sql=%fbbin%\isql.exe
set svc=%fbbin%\instsvc.exe
::
set def=%1
SET fpc=C:\FPC\bin\i386-win32\ppc386.exe -Mdelphi -B -FE"win32" -d %def%
del win32\*.* /Q > NUL 2>&1
%fpc% -Fu"C:\FPC\units\i386-win32\fcl-base" %udflib%.dpr
::
%svc% stop > NUL 2>&1
echo svc.stop.rc=[%errorlevel%]
del %fbudf%\%udflib%.dll > NUL 2>&1
echo del.fbudf.rc=[%errorlevel%]
copy win32\%udflib%.dll %fbudf% > NUL 2>&1
echo copy.fbudf.rc=[%errorlevel%]
%svc% start > NUL 2>&1
echo svc.start.rc=[%errorlevel%]
isql -i myudf.sql localhost:dev

and the sql script:
-- myudf.sql
------------
drop external function MYINT;
drop external function MYPCHAR;
commit;

DECLARE EXTERNAL FUNCTION MYINT RETURNS INTEGER BY VALUE ENTRY_POINT
'MYINT' MODULE_NAME 'MYUDF.DLL';
commit;
select cast(f_lrtrim(rdb$function_name)||' /
'||f_lrtrim(rdb$module_name)||' / '||f_lrtrim(RDB$ENTRYPOINT) as
varchar(60)) function_definition
from rdb$functions where (f_lrtrim(rdb$function_name)='MYINT');
select MYINT() from rdb$database;
commit;

DECLARE EXTERNAL FUNCTION MYPCHAR RETURNS CSTRING(20) FREE_IT
ENTRY_POINT 'MYPCHAR' MODULE_NAME 'MYUDF.DLL';
commit;
select cast(f_lrtrim(rdb$function_name)||' /
'||f_lrtrim(rdb$module_name)||' / '||f_lrtrim(RDB$ENTRYPOINT) as
varchar(60)) function_definition
from rdb$functions where (f_lrtrim(rdb$function_name)='MYPCHAR');
commit;
select MYPCHAR() from rdb$database;
commit;

> Also you have to check that your udf realy export requested functions.
How to do so ? I mean, is there any tool to check it after the dll is
built ?

> Another good tool is proces explorer and when FB will load function like
> sleep, you are able to check what is realy loaded.
I did that and I noticed that FB 2.1 don't link any more the dll
after shutting down.

> And finaly, check that ib_util is present in system and is in 64 bit
version.
For the moment, I test on 32 bit only. When all will be fine, it will
be done on 64 bit. the ib_util.dll is present in udf folder.

here is myudf.dpr source:
library myudf;
uses
windows, SysUtils, Classes, math, IB_Util;
//
{$IFDEF WINDOWS}
{$IFNDEF FPC}
{$R *.RES}
{$ENDIF FPC}
{$ENDIF WINDOWS}

type
PInt = ^Longint;
// DECLARE EXTERNAL FUNCTION SLEEP INTEGER RETURNS INTEGER BY VALUE
ENTRY_POINT 'SLEEP' MODULE_NAME 'MYUDF.DLL';
function SLEEP(time:PINT):integer; cdecl;
begin
result:=0;
if time=nil then exit;
windows.Sleep(time^);
result := time^;
end;
// DECLARE EXTERNAL FUNCTION MYINT RETURNS INTEGER BY VALUE
ENTRY_POINT 'MYINT' MODULE_NAME 'MYUDF.DLL';
function MYINT: integer; cdecl;
begin
Result := 12345;
end;
// DECLARE EXTERNAL FUNCTION MYPCHAR RETURNS CSTRING(20) FREE_IT
ENTRY_POINT 'MYPCHAR' MODULE_NAME 'MYUDF.DLL';
{$IFDEF MYPCHAR}
const MY_STRING = '1.2.3.4.5';
function MYPCHAR: PChar; cdecl;
begin
Result := ib_util_malloc(Length(MY_STRING)+1);
StrCopy(Result,PChar(MY_STRING));
end;
{$ENDIF MYPCHAR}
exports
SLEEP, MYINT
{$IFDEF MYPCHAR}
, MYPCHAR
{$ENDIF MYPCHAR}
;
begin
end.