UDF Oluşturma Firebird / Interbase

Yazdığınız makaleleri ve üyelerimizin işine yarayacağını düşündüğünüz kodlarınızı gönderebilirsiniz. Bu foruma soru sormayın!
Cevapla
Kullanıcı avatarı
Fatih!
Kıdemli Üye
Mesajlar: 1172
Kayıt: 26 Kas 2004 10:46
Konum: Malatya
İletişim:

UDF Oluşturma Firebird / Interbase

Mesaj gönderen Fatih! »

UDF, kısacası database ile yaptıramadagımız matematiksel yada parse etme işlemlerimizi rahatlıkla yaptırmamızı yarayan dll dosyalarıdır. Bunları Delphi ile rahatlıkla yazabilirsiniz.UDF ile neler yaptırabiliriz?
UDF ile aklınıza gelebilecek her türlü kolaylıgı saglayabilirsiniz. Mesala Eger kişi veritabanı alanına dogum tarihini girerse ve siz yaşını hesaplamak isterseniz bunu veritabanına yaptırabilirsiniz.Aksi durumda bunu programınızdan kod yazarak yapmak zorunda kalacaktınız. Peki, gerçekte kod yazmak dogru mu? Her ikisi de aynı işlemi yapmasına ragmen kod yazmak dogru degildir. Neden? Çünkü, SQL Explorer ya da başka programlar ile veri girilmek istendiginde sizin programınız çalışmadıgından yaş hesaplanmayacaktır oysa ki, UDF Kullanıldıgında başka programlardan dogum tarihi girilmesine ragmen yaş hesaplama işlemi yapılır. Bu da bizim Veritabanımızın daha stabil çalışması anlamına gelecektir. UDF Kullanırken bazı noktalara dikkat edilmesi gerekir bunlardan en önemlisi Null (Degersiz veya boş veri) alan kullanılmamasıdır.

Bir UDF oluşturup kullanmak için öncelikle udf nin kullanacağı, içinde fonksiyon bulunan bir dll lemiz olmalı

Dll hazırlamak için önce File-New menüsünden Other seçeneğini seçtikten sonra çıkan pencerenin New sekmesindeki DLL Wizad’ı seçin.
Bu işlemden sonra File-New menüsünden Unit' Tıklayıp Projeye yeni bir unit ekliyoruz.

Unit1 i aşağıdaki gibi Düzenleyin

Resim

Unit1 i yukarıdaki gibi tasarladıktan dll bölümüne geçip aşağıdaki Düzenlemeyi yapalım

Resim

DLL'yi Derlemeden Öncce Projeyi UDF_TOPLA ismiyle Kaydedin

> Dll dosyaları F9 tuşu ile çalıştırılmazlar. Derlemek için Project-Build UDF_TOPLA seçeneğini kullanmalısınız. Bu işlem sonrasında proje exe olarak değil dll uzantısına sahip olacaktır. Derlediğinizde herhangi bir hata yoksa projeyi kaydettiğiniz yerde UDF_TOPLA.DLL Dosyasını Gööreceksiiniz.



Oluşturduğunuz DLL'yi firebirdin yada interbasenin udf klasörüne kopyalayın.

benim pc de firebird dizini C:\Program Files\Firebird\Firebird_1_5\UDF

interbase udf dizini C:\Program Files\Borland\InterBase\UDF de bulunuyor

udf yi interbaseye tanıtmak için aşağıdaki kodu kullaanıyoruz.

Kod: Tümünü seç

DECLARE EXTERNAL FUNCTION UDFEM
INTEGER,
INTEGER
RETURNS INTEGER BY VALUE
ENTRY_POINT 'Topla' MODULE_NAME 'UDF_TOPLA'
DECLARE EXTERNAL FUNCTION Udf Yi Tanımlamayı Sağlıyor. Bundan Sonra Bir Ad Seçiyoruz. Ben Udfem Yaptım. Daha Sonra Dll'de Kullandığımız Parametrelerin Tipini Hyazıyoruz. Fonksiyonda İ Ve J Adında İki Parametremmiz Olduğu İçin Ve Tipleride İnteger Olduğu İçin İki Nteger Tipi Göseriyoruz. Birden Fazlaysa Parametre Sayısı Tiplerin Arasına Virgül Ekliyoruz.

Daha sonra RETURNS yazıp fonksiyon tipini integer seçiyoruz. returnstan sonraki tip tanımına udf den dönen değer eklenir. udf den tek değeröner. tıpkı fonksiyon gibi. zaten buda IB / FB fonksiyonu.. daha sonra BY VALUE yazıyoruz. BY VALUE yerine BY reference yazabiliriz. siz BY VALUE kuullanın. sonra ENTRY_POINT tırnak arasında dll de kullandığımız fonksiyon ismini yazıyoruz. son olarak MODULE_NAME yazıp tırnak arasında dll ismini uzantısını kullanmadan yazıyoruz.



Tools> SQL Editörü açıp oraya şu kodu yazarak etkisini görebilirsiniz

select UDFEM (1001,202) from rdb$database



rdb$database > UDF bilgilerini tutan sistem tablolarından biridir.



Kod: Tümünü seç

Pointer Tipli UDF
Yukarıda gördüğümüz sonuç olarak integer tipte değer döndürüyor. şimdi pointer tipte bir fonksiyon yazalım.

bunun için yukarıdaki projeye ekleme yapabileceğimiz gibi yeni bir projeyede başlaabiliriz.ben varolan projeye ekleme yaptım.

Resim

Aynı Fonksiyonu Aşağıdaki şekildede yazabiliriz.ib / fb ye tanıtma şekli aynıdır.

Kod: Tümünü seç

function Pointer_Topla_2 (Width,Height:PInteger):Integer;
begin
Result:=Width^+Height^;
end;
buı şekilde herhangi bir hata verirse interface hemen sonra fonksiyon tanımından hemen önce

Kod: Tümünü seç

type
  PInteger = ^Integer;
şeklinde tip tanımı yapın



Aşağıdaki kodla ib / fb ye tanıtın.

Kod: Tümünü seç

DECLARE EXTERNAL FUNCTION UDFEM_2

    INTEGER,

    INTEGER

RETURNS INTEGER BY VALUE

ENTRY_POINT 'Pointer_Topla' MODULE_NAME 'UDF_TOPLA'

 
Projenin DLL Sekmesi aşağıdaki şekilde olmalı


Resim

Tools> SQL Editörü açıp oraya şu kodu yazarak etkisini görebilirsiniz

Kod: Tümünü seç

select_2 UDFEM (1001,202) from rdb$database


String Tipli UDF
String tipli UDFler yazabilmek için IB / FB nin ib_util.dll ve ib_util.pas dosyalının yolunu Delphinin Library Path ına eklemeniz gerekecek. daha sonra ib_util.dll dosyasını Windowsun SYSTEM Dizinine Kopyalayın.

yine benim pc mde ib_util.dll dosyası firebird C:\Program Files\Firebird\Firebird_1_5\bin

interbase C:\Program Files\Borland\InterBase\bin

ib_util.pas dosyası firebird C:\Program Files\Firebird\Firebird_1_5\include

interbase C:\Program Files\Borland\InterBase\SDK\include dizinlerinde bulunuyor.

Bu işlemden sonra untinin interface deyiminden sonra uses SysUtils,ib_util; unit isimlerini ekliyoruz.

Şimdi Bir örnek yapalım. Aşağıdaki fonksiyon stringin sonundaki boşlukları atıyor.

sz parametresine stringinizi CNT parametresinede stringin uzunluğunu atayın. UDF DLL lerimizde Pchar String tip anlamına gelir..

Kod: Tümünü seç

function strornek (sz: PChar; var Cnt: Integer): PChar;
var
i: Integer;
begin
if (sz = nil) then
result := nil
else begin
i := 0;
while ((sz <> #0) and (i < cnt)) do Inc(i);
result := ib_util_malloc(i+1);
Move(sz[0], result[0], i);
result := #0;
end;
end;


udf yi ib/ fb ye tanıtma kodu aşağıdaki gibi olmalı.

Kod: Tümünü seç

DECLARE EXTERNAL FUNCTION UDFEM_4
CSTRING(64),
INTEGER
RETURNS CSTRING(64) FREE_IT
ENTRY_POINT 'strornek' MODULE_NAME 'UDF_TOPLA'


Burada farklı olartak gördüğümüz CSTRING(64) string tipini işaret ediyor. 64 stringin uzunluğu.FREE_IT ise udf çalıştıktan sonra dll yi hafızadan siliyor. String tiplr için bunu mutlaka yapmalısınız.Diğer Tiplerde kullanmıyoruz.



Karakter uzunlugunu hesaplama Delphi Dll Kodu:

Kod: Tümünü seç

function TEST_TrimLen (val: PChar): integer; stdcall;
begin
Result := -1;
if val[0] = #0 then Exit;
Inc(val); 
Result := Length(Trim(val));
end;


DECLARE EXTERNAL FUNCTION TEST_TRIMLEN
CSTRING(20)
RETURNS INTEGER BY VALUE
ENTRY_POINT 'TEST_TrimLen' MODULE_NAME 'UDF_Ornek';

 
En son Fatih! tarafından 24 Eyl 2005 06:25 tarihinde düzenlendi, toplamda 3 kere düzenlendi.
Kullanıcı avatarı
Fatih!
Kıdemli Üye
Mesajlar: 1172
Kayıt: 26 Kas 2004 10:46
Konum: Malatya
İletişim:

Mesaj gönderen Fatih! »

IB Expert'le UDF Oluşturma

UDFsa sağ tıklayıp New UDF dediğinizde aşağıdaki gibi bir pencere gelecektir

Resim
delphi_programmer
Üye
Mesajlar: 53
Kayıt: 01 Haz 2005 11:47

Mesaj gönderen delphi_programmer »

Sayın FAOSoft,

Bu değerli bilgileri verdiğiniz için öncelikle size teşekkür etmek istiyorum.
Gerçi siz bu bilgileri 2004'te vermişsiniz ama benim bugün işime yaradı.

Ancak bir yerde takıldım ve bu konuda sizden yardım alabileceğimi düşünüyorum. Eminim takıldığım nokta küçük birşeydir ama ne yazık ki çözemedim henüz.

Müsaadenizle hemen anlatayım.

Bir UDF yapıyorum. Görevi mail göndermek. (Ancak sorunum mail gönderme işlemleriyle alakalı değil tabii)

Delphi PROJECT kodum bu şekilde :

Kod: Tümünü seç

library Project1;

uses
  Unit1 in 'Unit1.pas';

exports

  mail_gonder;

begin
end.
Delphi UNIT kodum ise bu şekilde :

Kod: Tümünü seç

unit Unit1;

interface

uses ib_util,idsmtp,idmessage,forms;

function mail_gonder(var bilgi:pchar):pchar;stdcall;

implementation

function mail_gonder(var bilgi:pchar):pchar;
var
IdMsgSend:TIdMessage;
SMTP:TidSMTP;
begin
  IdMsgSend:=TIdMessage.Create(application);
  SMTP:=TidSMTP.Create(Application);
  with IdMsgSend do
      begin
         Body.Add(bilgi);
         From.Text := 'deneme';
         ReplyTo.EMailAddresses := 'test@test.com';
         Recipients.EMailAddresses := 'test@test.com';
         Subject := 'BASLIK';
         Priority := TIdMessagePriority(0); { Message Priority }
      end;

   SMTP.AuthenticationType := atLogin;
   SMTP.Username:='Test_Kullanicisi';
   SMTP.Password:='Test_Kullanici_Sifresi';

   {General setup}
   SMTP.Host := '10.10.1.8';
   SMTP.Port := 25;

   {now we send the message}
   SMTP.Connect;
   try
      SMTP.Send(IdMsgSend);
   finally
      SMTP.Disconnect;
      Result:='geriye_donus_degeri_onemli_degil';
   end;
   IdMsgSend.Free;
   SMTP.Free;
end;


end.
FireBird'de UDF oluşturmak için kullandığım kod ise şu şekilde :

Kod: Tümünü seç

DECLARE EXTERNAL FUNCTION F_MAIL_GONDER
    cstring(300)
RETURNS cstring FREE_IT
ENTRY_POINT 'mail_gonder' MODULE_NAME 'project1.dll'


Evet gördüğünüz gibi bu fonksiyonun dönüş değeri önemli değil.
Ve bir BILGI isminde bir parametre alıyor ve bunu unit içinde kullanıyor.

Ancak BILGI isimli değişkeni kullandığım zaman FireBird'de database bağlantısı kopuyor. (bir memory problemi oluşuyor anladığım kadarı ile)

Bunu biraz açıklayayım :
Örneğin şu anda UNIT kodu içinde

Kod: Tümünü seç

Body.Add(bilgi);
satırı var ve bu yüzden hata veriyor.

Ancak BILGI değişkenini UNIT içinde kullanmazsam problem yok. DLL dosyam işini yapıyor ve maili de gönderiyor ama tabii ki değişkenleri kullanmaz isek yapıyor bunu.

Örneğin

Kod: Tümünü seç

Body.Add("test");
şeklinde kullanırsam hata vermiyor.

Şimdi benim problemimin "UDF - Delphi - String" problemi olduğunu zannediyorum.

Gördüğünüz gibi değişkenim PCHAR olarak tanımlı.
Aynı zamanda ib_util uses'a eklenmiş durumda ve dll ve pas dosyaları da projemin olduğu klasörde bulunuyor.

Sizce String işlemlerinin neresinde hata yapıyorum ?

Cevabınız için şimdiden teşekkürler.
nedimtrc
Üye
Mesajlar: 23
Kayıt: 02 Nis 2007 09:31

Mesaj gönderen nedimtrc »

bende pchar yaptığım halde değişkenimi kullanamıyorum acaba atladığım bir noktamı var makaledeki tüm değerleri bilgileri aynen uyguladım ama nerde hata yaptığımı bulamıyorum. benimde sorunum tamammen delphiprogrammer arkadaşımızın ki sorununun aynısı
Cevapla