Konuyu Paylaş : facebook gplus twitter

Konuyu Oyla:
  • Derecelendirme: 2.5/5 - 2 oy
  • 1
  • 2
  • 3
  • 4
  • 5
C Dll indeki Callback Nasıl Çevrilir? (Çözüldü)
#1
typedef void (*onDeviceStatusChangedCallback) (terminal_status param);
DLL_EXPORT int AR_set_device_status_changed_cb(const char *terminal_no, onDeviceStatusChangedCallback cb);

Yukarıdaki kod bir C dll inin header dosyasından. Ben de bu kodları Delphi ye aşağıdaki gibi çevirdim.

TonDeviceStatusChangedCallback = procedure(param:TTerminalStatus) of object;

function AR_set_device_status_changed_cb(HInst:THandle; const TerminalNo: pAnsiChar; onDeviceStatusChangedCallback:TonDeviceStatusChangedCallback): LongInt;
var
 MyFunct: function (const TerminalNo: pAnsiChar; onDeviceStatusChangedCallback:TonDeviceStatusChangedCallback): LongInt; cdecl;
begin
 Result := 0;

 MyFunct:=GetProcAddress(HInst,'AR_set_device_status_changed_cb');
 if Assigned(MyFunct) then
   Result := MyFunct(TerminalNo,onDeviceStatusChangedCallback);
end;

Aynı soruyu stackowerflow a da sordum : Linkleri Görebilmeniz İçin Giriş yap veya Üye Ol
Stackowerflow da cevap var. Yalnız oradakileri de uyguladım. Ama accesslerden yine kurtulamadım. Bir çıkış yolu arıyorum. yardım eder misiniz?
Yukarıdaki c örneği için örnek kullanım:

void status_cb (terminal_status param)
{
   fprintf(stderr, "Terminal No: %s\n", param.terminal_no);
   fprintf(stderr, "Device Status: %d\n", param.status);

   if (param.status == DEVICE_STATUS_DISCONNECTED) {
       fprintf(stderr, "Cihaz Cradle Üzerinden Kaldırıldı\n");
   }
   else if (param.status == DEVICE_STATUS_PAIRED) {
       fprintf(stderr, "Cihaz Cradle Üzerine Konuldu\n");
   }
}

int main (int argc, char *argv[])
{
   int rc;

   if (parse_test_cmdline_and_start(argc, argv, TEST_INFO) < 0) {
       return 1;
   }

   onDeviceStatusChangedCallback cb = &status_cb;
   rc = AR_set_device_status_changed_cb (options.serial, cb);
   if (rc != AR_SUCCESS) {
       fprintf(stderr, "Error: %d => %s\n", rc, AR_strerror(rc));
   }
   sleep(60);

   return 0;
}
Cevapla
#2
(14-12-2017, Saat: 14:20)erkankurtaga Adlı Kullanıcıdan Alıntı: Linkleri Görebilmeniz İçin Giriş yap veya Üye Ol
typedef void (*onDeviceStatusChangedCallback) (terminal_status param);


DLL_EXPORT int AR_set_device_status_changed_cb(const char *terminal_no, onDeviceStatusChangedCallback cb);


Yukarıdaki kod bir C dll inin header dosyasından. Ben de bu kodları Delphi ye aşağıdaki gibi çevirdim.

TonDeviceStatusChangedCallback = procedure(param:TTerminalStatus) of object;

function AR_set_device_status_changed_cb(HInst:THandle; const TerminalNoTongueAnsiChar; onDeviceStatusChangedCallback:TonDeviceStatusChangedCallback): LongInt;
var
 MyFunct: function (const TerminalNoTongueAnsiChar; onDeviceStatusChangedCallback:TonDeviceStatusChangedCallback): LongInt; cdecl;
begin
 Result := 0;

 MyFunct:=GetProcAddress(HInst,'AR_set_device_status_changed_cb');
 if Assigned(MyFunct) then
   Result := MyFunct(TerminalNo,onDeviceStatusChangedCallback);
end;

Aynı soruyu stackowerflow a da sordum : Linkleri Görebilmeniz İçin Giriş yap veya Üye Ol
Stackowerflow da cevap var. Yalnız oradakileri de uyguladım. Ama accesslerden yine kurtulamadım. Bir çıkış yolu arıyorum. yardım eder misiniz?
Yukarıdaki c örneği için örnek kullanım:

void status_cb (terminal_status param)
{
   fprintf(stderr, "Terminal No: %s\n", param.terminal_no);
   fprintf(stderr, "Device Status: %d\n", param.status);

   if (param.status == DEVICE_STATUS_DISCONNECTED) {
       fprintf(stderr, "Cihaz Cradle Üzerinden Kaldırıldı\n");
   }
   else if (param.status == DEVICE_STATUS_PAIRED) {
       fprintf(stderr, "Cihaz Cradle Üzerine Konuldu\n");
   }
}

int main (int argc, char *argv[])
{
   int rc;

   if (parse_test_cmdline_and_start(argc, argv, TEST_INFO) < 0) {
       return 1;
   }

   onDeviceStatusChangedCallback cb = &status_cb;
   rc = AR_set_device_status_changed_cb (options.serial, cb);
   if (rc != AR_SUCCESS) {
       fprintf(stderr, "Error: %d => %s\n", rc, AR_strerror(rc));
   }
   sleep(60);

   return 0;
}

Size, uygun tanımları vermişler. Nerede sorun yaşıyorsunuz anlamadım ?
Mal sahibi, mülk sahibi
Hani bunun ilk sahibi ?
Mal da yalan mülk de yalan
Var biraz da sen oyalan...
WWW
Cevapla
#3
(14-12-2017, Saat: 14:30)Tuğrul HELVACI Adlı Kullanıcıdan Alıntı: Linkleri Görebilmeniz İçin Giriş yap veya Üye Ol
(14-12-2017, Saat: 14:20)erkankurtaga Adlı Kullanıcıdan Alıntı: Linkleri Görebilmeniz İçin Giriş yap veya Üye Ol
typedef void (*onDeviceStatusChangedCallback) (terminal_status param);


DLL_EXPORT int AR_set_device_status_changed_cb(const char *terminal_no, onDeviceStatusChangedCallback cb);


Yukarıdaki kod bir C dll inin header dosyasından. Ben de bu kodları Delphi ye aşağıdaki gibi çevirdim.

TonDeviceStatusChangedCallback = procedure(param:TTerminalStatus) of object;

function AR_set_device_status_changed_cb(HInst:THandle; const TerminalNoTongueAnsiChar; onDeviceStatusChangedCallback:TonDeviceStatusChangedCallback): LongInt;
var
 MyFunct: function (const TerminalNoTongueAnsiChar; onDeviceStatusChangedCallback:TonDeviceStatusChangedCallback): LongInt; cdecl;
begin
 Result := 0;

 MyFunct:=GetProcAddress(HInst,'AR_set_device_status_changed_cb');
 if Assigned(MyFunct) then
   Result := MyFunct(TerminalNo,onDeviceStatusChangedCallback);
end;

Aynı soruyu stackowerflow a da sordum : Linkleri Görebilmeniz İçin Giriş yap veya Üye Ol
Stackowerflow da cevap var. Yalnız oradakileri de uyguladım. Ama accesslerden yine kurtulamadım. Bir çıkış yolu arıyorum. yardım eder misiniz?
Yukarıdaki c örneği için örnek kullanım:

void status_cb (terminal_status param)
{
   fprintf(stderr, "Terminal No: %s\n", param.terminal_no);
   fprintf(stderr, "Device Status: %d\n", param.status);

   if (param.status == DEVICE_STATUS_DISCONNECTED) {
       fprintf(stderr, "Cihaz Cradle Üzerinden Kaldırıldı\n");
   }
   else if (param.status == DEVICE_STATUS_PAIRED) {
       fprintf(stderr, "Cihaz Cradle Üzerine Konuldu\n");
   }
}

int main (int argc, char *argv[])
{
   int rc;

   if (parse_test_cmdline_and_start(argc, argv, TEST_INFO) < 0) {
       return 1;
   }

   onDeviceStatusChangedCallback cb = &status_cb;
   rc = AR_set_device_status_changed_cb (options.serial, cb);
   if (rc != AR_SUCCESS) {
       fprintf(stderr, "Error: %d => %s\n", rc, AR_strerror(rc));
   }
   sleep(60);

   return 0;
}

Size, uygun tanımları vermişler. Nerede sorun yaşıyorsunuz anlamadım ?

Orada anlatılanların hepsini denedim. özellikle ikinci yöntemi daha çok denedim.

type
  TPaymentResultEvent = procedure(AResult: Integer) of object;

var
 gOnPaymentResult: TPaymentResultEvent;

procedure myPaymentResultCallback(AResult: Integer); cdecl;
begin
 if Assigned(gOnPaymentResult) then
   gOnPaymentResult(AResult);
end;

function ARPaymentItemCredit(HInst: THandle; const TerminalNo: PAnsiChar;
 const Description: PAnsiChar; Amount: Double; CurrencyID: Integer;
 ReceiptID: Integer; onPaymentResult: TPaymentResultEvent): Integer;
type
 TPaymentResultCallback = procedure(AResult: Integer); cdecl;
var
 MyFunct: function(const TerminalNo: PAnsiChar; const Description: PAnsiChar;
   Amount: Double; CurrencyID: Integer; ReceiptID: Integer;
   onPaymentResult: TPaymentResultCallback): Integer; cdecl;
begin
 @MyFunct := GetProcAddress(HInst, 'AR_payment_item_credit');
 if Assigned(MyFunct) then
 begin
   gOnPaymentResult := onPaymentResult;
   Result := MyFunct(TerminalNo, Description, Amount, CurrencyID, ReceiptID, @myPaymentResultCallback)
 end
 else
   Result := 0;
end;

Yalnız "myPaymentResultCallback" fonksiyonuna gelince fonksiyonu çalıştırmadan daha "begin" de access uyarısı veriyor.
İlk yöntemi de deneyince callback fonksiyonunu parametre olarak gönderince fonksiyon parametresi istiyor. İşin içinden çıkamadım açıkçası.
Cevapla
#4
Çok basitçe ve sadece; C/C++ header'ından size lazım olan metodların isimlerini ve tanımlarını buraya atarsanız çok daha kolay olacak. Fazlası ile karışık yazıyorsunuz. Access hatasından kastınız da Access Violation sanırım. Herneyse, gereken tanımları buraya yazarsanız ondan sonra bakalım. (Gördüğüm kadarı ile iki ayrı metod kullanıyorsunuz)
Mal sahibi, mülk sahibi
Hani bunun ilk sahibi ?
Mal da yalan mülk de yalan
Var biraz da sen oyalan...
WWW
Cevapla
#5
(14-12-2017, Saat: 15:10)Tuğrul HELVACI Adlı Kullanıcıdan Alıntı: Linkleri Görebilmeniz İçin Giriş yap veya Üye OlÇok basitçe ve sadece; C/C++ header'ından size lazım olan metodların isimlerini ve tanımlarını buraya atarsanız çok daha kolay olacak. Fazlası ile karışık yazıyorsunuz. Access hatasından kastınız da Access Violation sanırım. Herneyse, gereken tanımları buraya yazarsanız ondan sonra bakalım. (Gördüğüm kadarı ile iki ayrı metod kullanıyorsunuz)

Haklısınız iki ayrı metod. Buraya farklı oraya farklı methodlar attım. Bir tanesini çözebilirsek bu konuyu da öğrenmiş olacağım. Karışık olduğu için özür dilerim. Düzeltmek gerekirse eğer;

/*Callback tanımı*/
typedef void (*onDeviceStatusChangedCallback) (terminal_status param);

/*DLL fonksiyonu*/
DLL_EXPORT int AR_set_device_status_changed_cb(const char *terminal_no, onDeviceStatusChangedCallback cb);

Örnek Kullanım:

void status_cb (terminal_status param)
{
    fprintf(stderr, "Terminal No: %s\n", param.terminal_no);
    fprintf(stderr, "Device Status: %d\n", param.status);

    if (param.status == DEVICE_STATUS_DISCONNECTED) {
        fprintf(stderr, "Cihaz Cradle Üzerinden Kaldırıldı\n");
    }
    else if (param.status == DEVICE_STATUS_PAIRED) {
        fprintf(stderr, "Cihaz Cradle Üzerine Konuldu\n");
    }
}

int main (int argc, char *argv[])
{
    int rc;

    if (parse_test_cmdline_and_start(argc, argv, TEST_INFO) < 0) {
        return 1;
    }

    onDeviceStatusChangedCallback cb = &status_cb;
    rc = AR_set_device_status_changed_cb (options.serial, cb);
    if (rc != AR_SUCCESS) {
        fprintf(stderr, "Error: %d => %s\n", rc, AR_strerror(rc));
    }
    sleep(60);

    return 0;
}


Yukarıdaki c dll fonksiyon tanımlarına göre yaptıklarım;


{DLL Wrapper}


type
    TDeviceStatusChangedEvent = procedure(param:TTerminalStatus) of object;

var
    EDeviceStatusChangedEvent:TDeviceStatusChangedEvent;

procedure RunDeviceStatusChangedCB(param:TTerminalStatus);

function AR_set_device_status_changed_cb(HInst:THandle; const TerminalNoTongueAnsiChar;
  onDeviceStatusChangedCallback:TDeviceStatusChangedEvent): LongInt;

implementation

procedure RunDeviceStatusChangedCB(param:TTerminalStatus);
begin
    if not Assigned(EDeviceStatusChangedEvent) then
    EDeviceStatusChangedEvent(param);
end;

function AR_set_device_status_changed_cb(HInst:THandle; const TerminalNoTongueAnsiChar;
  onDeviceStatusChangedCallback:TDeviceStatusChangedEvent): LongInt;
type
    TDeviceStatusChangedCallBack = procedure(param:TTerminalStatus);cdecl;
var
    MyFunct: function (const TerminalNoTongueAnsiChar; onDeviceStatusChangedCallback:TDeviceStatusChangedCallBack): LongInt; cdecl;
begin
    Result := 0;
 
    @MyFunct:=GetProcAddress(HInst,'AR_set_device_status_changed_cb');
    if Assigned(MyFunct) then 
    begin
       EDeviceStatusChanged := onDeviceStatusChangedCallback;
       Result := MyFunct(TerminalNo,@RunDeviceStatusChangedCB);
    end;
end;


{DLL Wrapper son}

/*Kullanım örneği*/

procedure TForm2.DeviceStatusChanged(param:TTerminalStatus);
begin
  DeviceWait:=False;

  case param.DeviceStatus of
     DEVICE_STATUS_DISCONNECTED:begin
                                  DeviceOK:=False;
                                  AddMemo('Cihaz Cradle Üzerinden Kaldırıldı',True);
                                end;
        DEVICE_STATUS_CONNECTED,
           DEVICE_STATUS_PAIRED:begin
                                  DeviceOK:=True;
                                  AddMemo('Cihaz Bağlı');
                                end;
              DEVICE_STATUS_ALL,
          DEVICE_STATUS_UNKNOWN,
    DEVICE_STATUS_NOTREGISTERED:begin
                                  DeviceOK:=False;
                                  AddMemo('Cihaz Bağlı Değil',True);
                                end;
  end;
end;

procedure TForm2.RegisterDeviceStatusCallBack;
begin
  try
    SetCihazBilgi;
    rc := AR_set_device_status_changed_cb (DllHInst,SP(dtermno),DeviceStatusChanged);
    DeviceWait := rc = AR_SUCCESS;
  except
    DeviceWait := False;
  end;

  while DeviceWait and (DeviceOK=false) do Delay(100);
end;


Acess Violation Hatasına düşen Kısım RunDeviceStatusChangedCB fonksiyonu. Fonksiyon çalışmadan "Access Violation"  hatası veriyor.
Cevapla
#6
Aşağı yukarı aşağıdaki gibi bir yol izlemeniz gerekiyor:

type
  Terminal_Status = Integer; // ??? Bunun ne olduğunu bilmiyoruz, bizimle paylaşmamışsınız.

 TDeviceStatusChangedCallback = procedure(AParam : Terminal_Status); cdecl;
 TARSetDeviceStatusChangedCbFunc = function (terminal_no : PAnsiChar; ACallback : TDeviceStatusChangedCallback) : Integer; cdecl;

implementation

procedure MyCallBack(AParam : Terminal_Status);
begin
 // Burada sizin callback kodlarınız çalışacak..
end;

procedure Load;
var
 ARSetDeviceStatusChangedCbFunc : TARSetDeviceStatusChangedCbFunc;
 ALibHandle : THandle;
begin
 ALibHandle := LoadLibrary('?????.dll');

 @ARSetDeviceStatusChangedCbFunc := GetProcAddress(ALibHandle, 'AR_set_device_status_changed_cb');

 if @ARSetDeviceStatusChangedCbFunc <> nil then
 begin
   ARSetDeviceStatusChangedCbFunc(PAnsiChar('Birşey'), @MyCallBack);
 end;
end;
Mal sahibi, mülk sahibi
Hani bunun ilk sahibi ?
Mal da yalan mülk de yalan
Var biraz da sen oyalan...
WWW
Cevapla
#7
(14-12-2017, Saat: 16:03)Tuğrul HELVACI Adlı Kullanıcıdan Alıntı: Linkleri Görebilmeniz İçin Giriş yap veya Üye OlAşağı yukarı aşağıdaki gibi bir yol izlemeniz gerekiyor:

type
  Terminal_Status = Integer; // ??? Bunun ne olduğunu bilmiyoruz, bizimle paylaşmamışsınız.

 TDeviceStatusChangedCallback = procedure(AParam : Terminal_Status); cdecl;
 TARSetDeviceStatusChangedCbFunc = function (terminal_no : PAnsiChar; ACallback : TDeviceStatusChangedCallback) : Integer; cdecl;

implementation

procedure MyCallBack(AParam : Terminal_Status);
begin
 // Burada sizin callback kodlarınız çalışacak..
end;

procedure Load;
var
 ARSetDeviceStatusChangedCbFunc : TARSetDeviceStatusChangedCbFunc;
 ALibHandle : THandle;
begin
 ALibHandle := LoadLibrary('?????.dll');

 @ARSetDeviceStatusChangedCbFunc := GetProcAddress(ALibHandle, 'AR_set_device_status_changed_cb');

 if @ARSetDeviceStatusChangedCbFunc <> nil then
 begin
   ARSetDeviceStatusChangedCbFunc(PAnsiChar('Birşey'), @MyCallBack);
 end;
end;

Teşekkür ederim. Bahsettiğiniz şekilde de denedim.Derleyici MyCallBack için "Variable required" hatası döndürüyor.
Cevapla
#8
@Tuğrul HELVACI Hocam çok ilginiz için teşekkürler. Bu sorunun cevabı dediğiniz gibi stackoverflow da ilgili konuda verilmişti. Ben dikkatsizlik sonucu çözümü göremedim. Boş yere vaktinizi aldım. Hakkınızı helal edin. Sorunum şuymuş.

procedure RunDeviceStatusChangedCB(param:TTerminalStatus);
 fonksiyonu
RunDeviceStatusChangedCB(param:TTerminalStatus);cdecl;
 
olması gerekiyormuş. Biraz geç oldu ama yoğunluktan yazamadım. Bu sorunun cevabı burda : Linkleri Görebilmeniz İçin Giriş yap veya Üye Ol
Cevapla
#9
(20-12-2017, Saat: 13:29)erkankurtaga Adlı Kullanıcıdan Alıntı: Linkleri Görebilmeniz İçin Giriş yap veya Üye Ol@Tuğrul HELVACI Hocam çok ilginiz için teşekkürler. Bu sorunun cevabı dediğiniz gibi stackoverflow da ilgili konuda verilmişti. Ben dikkatsizlik sonucu çözümü göremedim. Boş yere vaktinizi aldım. Hakkınızı helal edin. Sorunum şuymuş.

procedure RunDeviceStatusChangedCB(param:TTerminalStatus);
 fonksiyonu
RunDeviceStatusChangedCB(param:TTerminalStatus);cdecl;
 
olması gerekiyormuş. Biraz geç oldu ama yoğunluktan yazamadım. Bu sorunun cevabı burda : Linkleri Görebilmeniz İçin Giriş yap veya Üye Ol

Rica ederim, helal olsun. Önemli olan, sorununuzu halletmiş olmanız.
Mal sahibi, mülk sahibi
Hani bunun ilk sahibi ?
Mal da yalan mülk de yalan
Var biraz da sen oyalan...
WWW
Cevapla
#10
Konu aslında fonksiyon çağırım düzeni, yani fonksiyon parametrelerinin hangilerinin stack ve/veya CPU register'da tahsis edilişi ile ilgili.

C dilinde fonksiyonlar varsayılan olarak cdecl direktifini kullanır.Bunun anlamı fonksiyon parametrelerinin tamamı stack'de tutulur.
Delphi'de fonksiyonlar varsayılan olarak Register direktifini kullanır.Bunun anlamı fonksiyon parametrelerinin 3 tanesine kadarı CPU register'larda tutulurken diğerleri stack'de tutulur.
Delphi'deki Register direktifinin karşılığı C dilinde __fastcall'dır.

Bahsettiklerimi gözlemlemek adına, Delphi'de yazdığınız fonksiyonlara breakpoint koyup CPU ekranından kontrol edebilirsiniz.
Daha detaylı bilgi için Linkleri Görebilmeniz İçin Giriş yap veya Üye Ol gözatabilirsiniz.
My name is nobody.
WWW
Cevapla

Konuyu Paylaş : facebook gplus twitter



Konu ile Alakalı Benzer Konular
Konular Yazar Yorumlar Okunma Son Yorum
  Aynı türden iki class'ı nasıl klonlarız? uparlayan 20 685 15-09-2018, Saat: 10:41
Son Yorum: ismailkocacan
  Client tarafında yapılan tüm değişiklikleri tek seferde veritabanına nasıl yazarım adelphiforumz 3 123 12-09-2018, Saat: 22:30
Son Yorum: ssahinoglu
  [ ÇÖZÜLDÜ ] RAD Studio Community Edition ? BY-HAYALET 3 159 11-09-2018, Saat: 10:20
Son Yorum: BY-HAYALET
  pascal script ile QuickReport nesnelerine nasıl erişim yapılır theSinan 4 266 01-08-2018, Saat: 08:51
Son Yorum: Kuri_YJ
  (Çözüldü) function kullanımı Dostk 3 191 24-07-2018, Saat: 14:54
Son Yorum: Dostk



Konuyu Okuyanlar: 1 Ziyaretçi