(接上一篇)
如何编写interbase udf
warton译
怎么编写字符串和日期型处理函数的udf呢?
下面编写一个“left“函数
内存分配问题:
如果你使用ib(interbase)5.1以下版本的话,在你的单元文件中键入下面的声明:
function malloc(bytes: integer): pointer; cdecl; external msvcrt.dll;
如果你有5.5以上的版本,你就不需要这么做了。这样,先确定ib_util.pas 文件在你的编译器可以找到的路径中,并且ib_util.dll也在你的搜索路径之中。
最简单的方法是放到的库可搜索到的路径。
c:\program files\interbase corp\interbase\include
然后复制
c:\program files\interbase corp\interbase\lib\ib_util.dll
到你的windows系统目录下(典型的是:c:\windows ystem)。最后在你的单元文件的use子句中将ib_util.pas加进去
uses
…,
ib_util;
为什么有如此奇特的内存分配?为什么我不能用allocmem分配内存,或者其它方法?问题很简单:你不能,所以不要问!更复杂的问题是每一个编译器使用它喜欢的算法来进行内存管理,这是被操作系统控制着的。例如,vc和delphi管理内存的方式不同,猜这是为什么?ib是在vc下编译的,在5.5以前的版本中,你必须直接指定运行库。在ib5.5之后,ib给了一个ib调用使得这成为可能。既然这样,那我们继续进行编写字符串操作的函数。
构建函数
在新的单元文件中,作如下声明:
function left(sz: pchar; cnt: integer): pchar; cdecl; export;
在函数实现部分:
(* return the cnt leftmost characters of sz *)
function left(sz: pchar; var cnt: integer): pchar;
var
i: integer;
begin
if (sz = nil) then
result := nil
else begin
i := 0;
while ((sz[i] <> #0) and (i < cnt)) do inc(i);
result := ib_util_malloc(i+1);
move(sz[0], result[0], i);
result[i] := #0;
end;
end;
在你的工程文件中,在“exports“部分键入:
exports
modulo,
left;
now,再次编译工程项目….
现在,为了使用函数,在isql中重新连接数据库,输入:
declare external function f_left
cstring(64), integer
returns cstring(64) free_it
entry_point left module_name dll name minus “.dll”;
测试这个函…
select f_left(hello, 3) from rdb$database
仍然相当简单,哈?
上我们来编写一个时间函数
在ib6中,有三种不同的时期类型被支持,date,time,和timestamp,与ib5.5及以前老版本中的相比,timestamp 的数据类型实质上相当于ib5.5的date类型。
为了在你的程序中”decode”和”encode”这些类型。你应该了解一点ib api相关的信息。输入以下代码:
interface
…
type
tm = record
tm_sec : integer; // seconds
tm_min : integer; // minutes
tm_hour : integer; // hour (0–23)
tm_mday : integer; // day of month (1–31)
tm_mon : integer; // month (0–11)
tm_year : integer; // year (calendar year minus 1900)
tm_wday : integer; // weekday (0–6) sunday = 0)
tm_yday : integer; // day of year (0–365)
tm_isdst : integer; // 0 if daylight savings time is not in effect)
end;
ptm = ^tm;
isc_timestamp = record
timestamp_date : long;
timestamp_time : ulong;
end;
pisc_timestamp = ^isc_timestamp;
implementation
…
procedure isc_encode_timestamp (tm_date: ptm;
ib_date: pisc_timestamp);
stdcall; external ibase_dll;
procedure isc_decode_timestamp (ib_date: pisc_timestamp;
tm_date: ptm);
stdcall; external ibase_dll;
procedure isc_decode_sql_date (var ib_date: long;
tm_date: ptm);
stdcall; external ibase_dll;
procedure isc_encode_sql_date (tm_date: ptm;
var ib_date: long);
stdcall; external ibase_dll;
procedure isc_decode_sql_time (var ib_date: ulong;
tm_date: ptm);
stdcall; external ibase_dll;
procedure isc_encode_sql_time (tm_date: ptm;
var ib_date: ulong);
stdcall; external ibase_dll;
现在我们写日期udf:
在单元文件的interface部分,输入声明:
function year(var ib_date: long): integer; cdecl; export;
function hour(var ib_time: ulong): integer; cdecl; export;
在implementation(实现)部分,输入:
function year(var ib_date: long): integer;
var
tm_date: tm;
begin
isc_decode_sql_date(@ib_date, @tm_date);
result := tm_date.tm_year + 1900;
end;
function hour(var ib_time: ulong): integer;
var
tm_date: tm;
begin
isc_decode_sql_time(@ib_time, @tm_date);
result := tm_date.tm_hour;
end;
最好,在你的工程文件中:在““部分,输入:
exports
modulo,
left,
year,
hour;
现在编译工程…
为了使用这个函数,就像上面那样:用isql连接数据库,输入:
declare external function f_year
date
returns integer by value
entry_point year module_name dll name minus “.dll”;
declare external function f_hour
time
returns integer by value
entry_point hour module_name dll name minus “.dll”;
最后再测试一下看!
select f_year(cast(7/11/00 as date)) from rdb$database
这一部分并非像前面字符串和整数那样操作哪样了,但是还是相当…simple,哼!
编写linux/unix平台的udf
(未完待续!!)
