AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Programmieren allgemein Hilfe bei einem Callback einer C++ Dll nach Delphi
Thema durchsuchen
Ansicht
Themen-Optionen

Hilfe bei einem Callback einer C++ Dll nach Delphi

Ein Thema von Wal · begonnen am 7. Jul 2011 · letzter Beitrag vom 13. Jul 2011
Antwort Antwort
Wal

Registriert seit: 22. Sep 2006
57 Beiträge
 
#1

Hilfe bei einem Callback einer C++ Dll nach Delphi

  Alt 7. Jul 2011, 16:10
Dll Callback in C++ deklariert
Code:
typedef BOOL (*RESPONSE_FUNC)(UCHAR ucChannel, UCHAR ucResponseMsgID);
typedef BOOL (*CHANNEL_EVENT_FUNC)(UCHAR ucChannel, UCHAR ucEvent);

typedef void (*P_ANT_ARF)(RESPONSE_FUNC, UCHAR*);
typedef void (*P_ANT_AEF)(UCHAR, CHANNEL_EVENT_FUNC, UCHAR*);
Aufruf:
Code:
static BOOL Test_ChannelCallback(UCHAR ucChannel_, UCHAR ucEvent_);
static BOOL Test_ResponseCallback(UCHAR ucChannel_, UCHAR ucMessageId_);

ANT_AssignResponseFunction(Test_ResponseCallback, aucResponseBuffer);
ANT_AssignChannelEventFunction(USER_ANTCHANNEL,Test_ChannelCallback, aucChannelBuffer);
Delphiübersetzung von mir
Code:
function RESPONSE_FUNC(ucANTChannel: UCHAR; ucResponseMsgID: UCHAR): Boolean;
function CHANNEL_EVENT_FUNC(ucANTChannel: UCHAR; ucEvent: UCHAR): Boolean;

TFNANT_AssignResponseFunction = procedure(RESPONSE_FUNC: Pointer; var pucResponseBuffer: Array of UCHAR); cdecl;
TFNANT_AssignChannelEventFunction = procedure(ucANTChannel: UCHAR; CHANNEL_EVENT_FUNC: Pointer; var pucChannelBuffer: Array of UCHAR); cdecl;
Aufruf:
Code:
ANT_AssignResponseFunction(@RESPONSE_FUNC, aucResponseBuffer);
ANT_AssignChannelEventFunction(USER_ANTCHANNEL, @CHANNEL_EVENT_FUNC, aucChannelBuffer);
Der Callback funktioniert, aber ucResponseMsgID und ucEvent ist immer 0.
Muß ich noch was beachten ?

Gruß Wal
  Mit Zitat antworten Zitat
Benutzerbild von DeddyH
DeddyH

Registriert seit: 17. Sep 2006
Ort: Barchfeld
27.541 Beiträge
 
Delphi 11 Alexandria
 
#2

AW: Hilfe bei einem Callback einer C++ Dll nach Delphi

  Alt 8. Jul 2011, 08:15
Müssten die beiden Callback-Funktionen nicht auch als cdecl deklariert werden?
Detlef
"Ich habe Angst vor dem Tag, an dem die Technologie unsere menschlichen Interaktionen übertrumpft. Die Welt wird eine Generation von Idioten bekommen." (Albert Einstein)
Dieser Tag ist längst gekommen
  Mit Zitat antworten Zitat
Wal

Registriert seit: 22. Sep 2006
57 Beiträge
 
#3

AW: Hilfe bei einem Callback einer C++ Dll nach Delphi

  Alt 8. Jul 2011, 15:20
Hat sich im Moment erledigt, habe die Dll mit VC++ 2010 Express neu erzeugt und es hat gefunzt.

Die Callback's sind wie oben zu sehen als cdecl deklariert. Die Funktionen sind ja Progammintern, die bei einem Callback angesprungen werden.

Trotzdem Danke, brauche ja evtl. noch Hilfe, da ich noch nicht alles übersetzt habe.

P.S. Das Ganze gehört zur Ant_Dll, mit dem man Ant+ Sensoren z.B. Garmin Pulsgurt, Trittfrequenzsensor über einen Ant+ USB-Stick z.B. Garmin USB Stick direkt in dem PC einlesen kann.
  Mit Zitat antworten Zitat
Wal

Registriert seit: 22. Sep 2006
57 Beiträge
 
#4

AW: Hilfe bei einem Callback einer C++ Dll nach Delphi

  Alt 9. Jul 2011, 12:21
Leider zu früh gejubelt, war nur Zufall das die Werte in ucEvent und ucResponseMsgID gestimmt hatten.
Mit aucResponseBuffer und aucChannelBuffer kann ich arbeiten, da in diesen Arrays die richtigen Daten stehen und ich meine Herzfrequenz richtig auslesen kann.

Habe die Source der Ant_Dll hochgeleden, wäre nett wenn jemand mal drüberschauen könnte.
Angehängte Dateien
Dateityp: zip ANT_DLL.zip (23,1 KB, 27x aufgerufen)
  Mit Zitat antworten Zitat
Wal

Registriert seit: 22. Sep 2006
57 Beiträge
 
#5

AW: Hilfe bei einem Callback einer C++ Dll nach Delphi

  Alt 9. Jul 2011, 12:50
Müssten die beiden Callback-Funktionen nicht auch als cdecl deklariert werden?

Das habe ich eben probiert, was soll ich sagen ... es geht.
Warum muß ich die Funktion die nur Programmintern ist und auf die die Callbackprocedure verweist, auch mit cdecl deklarieren ?

Code:
unit ant_dll;

interface

uses Windows, Forms, SysUtils, Dialogs;

const
  USER_ANTCHANNEL = 0;
  USER_NETWORK_NUM = 0;
  // Indexes into message recieved from ANT
  MESSAGE_BUFFER_DATA1_INDEX         = 0;
  MESSAGE_BUFFER_DATA2_INDEX         = 1;
  MESSAGE_BUFFER_DATA3_INDEX         = 2;
  MESSAGE_BUFFER_DATA4_INDEX         = 3;
  MESSAGE_BUFFER_DATA5_INDEX         = 4;
  MESSAGE_BUFFER_DATA6_INDEX         = 5;
  MESSAGE_BUFFER_DATA7_INDEX         = 6;
  MESSAGE_BUFFER_DATA8_INDEX         = 7;
  MESSAGE_BUFFER_DATA9_INDEX         = 8;
  MESSAGE_BUFFER_DATA10_INDEX        = 9;
  MESSAGE_BUFFER_DATA11_INDEX        = 10;
  MESSAGE_BUFFER_DATA12_INDEX        = 11;
  MESSAGE_BUFFER_DATA13_INDEX        = 12;
  MESSAGE_BUFFER_DATA14_INDEX        = 13;



type
  TMyArray1 = array[0..255] of AnsiChar;
  TMyArray2 = array[0..9] of Byte;
  TMyArray3 = array[0..16] of Byte;

  ////////////////////////////////////////////////////////////////////////////////////////
  // The following functions are used to manage the USB connection to the module
  ////////////////////////////////////////////////////////////////////////////////////////
  TFNANT_GetDeviceUSBInfo            = function(ucUSBDeviceNum: UCHAR; var pucProductString: TMyArray1; var pucSerialString: TMyArray1): Boolean; cdecl;
  TFNANT_GetDeviceUSBPID             = function(var pusPID: USHORT): Boolean; cdecl;
  TFNANT_GetDeviceUSBVID             = function(var pusVID: USHORT): Boolean; cdecl;
  TFNANT_GetDeviceSerialNumber       = function: ULONG; cdecl;

  TFNANT_Init                        = function(ucUSBDeviceNum: UCHAR; usBaudrate: USHORT): Boolean; cdecl; //Initializes and opens USB connection to the module
  TFNANT_Close                       = procedure; cdecl; //Closes the USB connection to the module
  TFNANT_LibVersion                  = function: AnsiChar; cdecl;
 
  TFNANT_AssignResponseFunction      = procedure(RESPONSE_FUNC: Pointer; var pucResponseBuffer: TMyArray2); cdecl;
  TFNANT_AssignChannelEventFunction  = procedure(ucANTChannel: UCHAR; CHANNEL_EVENT_FUNC: Pointer; var pucChannelBuffer: TMyArray3); cdecl;
  TFNANT_UnassignAllResponseFunctions = procedure; cdecl;   //Unassigns all response functions

  ////////////////////////////////////////////////////////////////////////////////////////
  // Config Messages
  ////////////////////////////////////////////////////////////////////////////////////////
  TFNANT_UnAssignChannel             = function(ucANTChannel: UCHAR): Boolean; cdecl;
  TFNANT_UnAssignChannel_RTO         = function(ucANTChannel: UCHAR; ulResponseTime: ULONG): Boolean; cdecl;

  TFNANT_AssignChannel               = function(ucANTChannel: UCHAR; ucChanType: UCHAR; ucNetNumber: UCHAR): Boolean; cdecl;
  TFNANT_AssignChannel_RTO           = function(ucANTChannel: UCHAR; ucChanType: UCHAR; ucNetNumber: UCHAR; ulResponseTime: ULONG): Boolean; cdecl;

  TFNANT_AssignChannelExt            = function(ucANTChannel: UCHAR; ucChanType: UCHAR; ucNetNumber: UCHAR; ucExtFlags: UCHAR): Boolean; cdecl;
  TFNANT_AssignChannelExt_RTO        = function(ucANTChannel: UCHAR; ucChanType: UCHAR; ucNetNumber: UCHAR; ucExtFlags: UCHAR; ulResponseTime: ULONG): Boolean; cdecl;

  TFNANT_SetChannelId                = function(ucANTChannel: UCHAR; usDeviceNumber: UShort; ucDeviceType: UCHAR; ucTransmissionType: UCHAR): Boolean; cdecl;
  TFNANT_SetChannelId_RTO            = function(ucANTChannel: UCHAR; usDeviceNumber: UShort; ucDeviceType: UCHAR; ucTransmissionType: UCHAR; ulResponseTime: ULONG): Boolean; cdecl;

  TFNANT_SetChannelPeriod            = function(ucANTChannel: UCHAR; usMesgPeriod: UShort): Boolean; cdecl;
  TFNANT_SetChannelPeriod_RTO        = function(ucANTChannel: UCHAR; usMesgPeriod: UShort; ulResponseTime: ULONG): Boolean; cdecl;

  TFNANT_SetChannelSearchTimeout     = function(ucANTChannel: UCHAR; ucSearchTimeout: UCHAR): Boolean; cdecl;
  TFNANT_SetChannelSearchTimeout_RTO = function(ucANTChannel: UCHAR; ucSearchTimeout: UCHAR; ulResponseTime: ULONG): Boolean; cdecl;

  TFNANT_SetChannelRFFreq            = function(ucANTChannel: UCHAR; ucRFFreq: UCHAR): Boolean; cdecl;
  TFNANT_SetChannelRFFreq_RTO        = function(ucANTChannel: UCHAR; ucRFFreq: UCHAR; ulResponseTime: ULONG): Boolean; cdecl;

  TFNANT_SetNetworkKey               = function(ucNetNumber: Byte; pucKey: Array of UCHAR): Boolean; cdecl;
  TFNANT_SetNetworkKey_RTO           = function(ucNetNumber: Byte; pucKey: Array of UCHAR; ulResponseTime: ULONG): Boolean; cdecl;

  TFNANT_SetTransmitPower            = function(ucTransmitPower: UCHAR): Boolean; cdecl;
  TFNANT_SetTransmitPower_RTO        = function(ucTransmitPower: UCHAR; ulResponseTime: UCHAR): Boolean; cdecl;

////////////////////////////////////////////////////////////////////////////////////////
// ANT Control messages
////////////////////////////////////////////////////////////////////////////////////////
  TFNANT_ResetSystem                 = function: Boolean; cdecl;

  TFNANT_OpenChannel                 = function(ucANTChannel: UCHAR): Boolean; cdecl;
  TFNANT_OpenChannel_RTO             = function(ucANTChannel: UCHAR; ulResponseTime: UCHAR): Boolean; cdecl;

  TFNANT_CloseChannel                = function(ucANTChannel: UCHAR): Boolean; cdecl;
  TFNANT_CloseChannel_RTO            = function(ucANTChannel: UCHAR; ulResponseTime: UCHAR): Boolean; cdecl;

  TFNANT_RequestMessage              = function(ucANTChannel: UCHAR; ucMessageID: UCHAR):Boolean; cdecl;

////////////////////////////////////////////////////////////////////////////////////////
// Threading
////////////////////////////////////////////////////////////////////////////////////////
  TFNANT_Nap                         = procedure(ulMilliseconds: ULONG); cdecl;

  function LoadAntDll: Boolean;
  function CloseAntDll: Boolean;

  function RESPONSE_FUNC(ucANTChannel: UCHAR; ucResponseMsgID: UChar): Boolean; cdecl; [SIZE="18"][COLOR="Red"]//<--Hier[/COLOR][/SIZE]
  function CHANNEL_EVENT_FUNC(ucANTChannel: UCHAR; ucEvent: UCHAR): Boolean; cdecl; [SIZE="18"][COLOR="Red"]//<--Hier[/COLOR][/SIZE]

var
  ANT_GetDeviceUSBInfo           : TFNANT_GetDeviceUSBInfo = Nil;
  ANT_GetDeviceUSBPID            : TFNANT_GetDeviceUSBPID = Nil;
  ANT_GetDeviceUSBVID            : TFNANT_GetDeviceUSBVID = Nil;
  ANT_GetDeviceSerialNumber      : TFNANT_GetDeviceSerialNumber = Nil;

  ANT_Init                       : TFNANT_Init = nil;
  ANT_Close                      : TFNANT_Close = nil;
  ANT_LibVersion                 : TFNANT_LibVersion = Nil;

  ANT_AssignResponseFunction     : TFNANT_AssignResponseFunction = Nil;
  ANT_AssignChannelEventFunction : TFNANT_AssignChannelEventFunction = Nil;
  ANT_UnassignAllResponseFunctions: TFNANT_UnassignAllResponseFunctions = Nil;


  ANT_ResetSystem                : TFNANT_ResetSystem = Nil;

  ANT_SetNetworkKey              : TFNANT_SetNetworkKey = Nil;

  ANT_AssignChannel              : TFNANT_AssignChannel = Nil;
  ANT_SetChannelId               : TFNANT_SetChannelId = Nil;
  ANT_SetChannelRFFreq           : TFNANT_SetChannelRFFreq = Nil;
  ANT_SetChannelPeriod           : TFNANT_SetChannelPeriod = Nil;
  ANT_OpenChannel                : TFNANT_OpenChannel = Nil;
  ANT_CloseChannel               : TFNANT_OpenChannel = Nil;
  ANT_RequestMessage             : TFNANT_RequestMessage = Nil;

  ANT_Nap                        : TFNANT_Nap = Nil;

  AntLib: HMODULE;

  ucNetKey: Array[0..7] of Byte = ($B9, $A5, $21, $FB, $BD, $72, $C3, $45);
  usDevicePID : Word;
  usDeviceVID : Word;
  ucResponseBuffer: TMyArray2;
  ucChannelBuffer: TMyArray3;
  ucDeviceDescription: TMyArray1;
   ucDeviceSerial: TMyArray1;
  ucLibVersion: AnsiChar;

implementation

uses
  antdefines, antmessage, frmMain;

function LoadAntDll: Boolean;
begin
  result := False;
  AntLib := LoadLibrary(PChar('ANT_DLL.dll'));
  if AntLib <> 0 then
  begin
    @ANT_Init                      := GetProcAddress(AntLib, 'ANT_Init');
    @ANT_Close                     := GetProcAddress(AntLib, 'ANT_Close');
    @ANT_ResetSystem               := GetProcAddress(AntLib, 'ANT_ResetSystem');
    @ANT_Nap                       := GetProcAddress(AntLib, 'ANT_Nap');
    @ANT_SetNetworkKey             := GetProcAddress(AntLib, 'ANT_SetNetworkKey');
    @ANT_GetDeviceUSBInfo          := GetProcAddress(AntLib, 'ANT_GetDeviceUSBInfo');
    @ANT_GetDeviceUSBVID           := GetProcAddress(AntLib, 'ANT_GetDeviceUSBVID');
    @ANT_GetDeviceUSBPID           := GetProcAddress(AntLib, 'ANT_GetDeviceUSBPID');
    //@ANT_GetDeviceSerialNumber     := GetProcAddress(AntLib, 'ANT_GetDeviceSerialNumber');
    @ANT_AssignChannel             := GetProcAddress(AntLib, 'ANT_AssignChannel');
    @ANT_SetChannelId              := GetProcAddress(AntLib, 'ANT_SetChannelId');
    @ANT_SetChannelRFFreq          := GetProcAddress(AntLib, 'ANT_SetChannelRFFreq');
    @ANT_SetChannelPeriod          := GetProcAddress(AntLib, 'ANT_SetChannelPeriod');
    @ANT_OpenChannel               := GetProcAddress(AntLib, 'ANT_OpenChannel');
    @ANT_CloseChannel              := GetProcAddress(AntLib, 'ANT_CloseChannel');
    @ANT_RequestMessage            := GetProcAddress(AntLib, 'ANT_RequestMessage');

    @ANT_AssignResponseFunction    := GetProcAddress(AntLib, 'ANT_AssignResponseFunction');
    @ANT_AssignChannelEventFunction := GetProcAddress(AntLib, 'ANT_AssignChannelEventFunction');
    @ANT_LibVersion                := GetProcAddress(AntLib, 'ANT_LibVersion');

    result := True;
    if
    (@ANT_Init=nil) or
    (@ANT_Close=nil) or
    (@ANT_ResetSystem=nil) or
    (@ANT_Nap=nil) or
    (@ANT_SetNetworkKey=nil) or
    (@ANT_GetDeviceUSBInfo=nil) or
    (@ANT_GetDeviceUSBVID=nil) or
    (@ANT_GetDeviceUSBPID=nil) or
    //(@ANT_GetDeviceSerialNumber=nil) or
    (@ANT_AssignChannel=nil) or
    (@ANT_SetChannelId=nil) or
    (@ANT_SetChannelRFFreq=nil) or
    (@ANT_SetChannelPeriod=nil) or
    (@ANT_OpenChannel=nil) or
    (@ANT_CloseChannel=nil) or
    (@ANT_RequestMessage=nil) or

    (@ANT_AssignResponseFunction=nil) or
    (@ANT_AssignChannelEventFunction=nil) or
    (@ANT_LibVersion=nil) then Showmessage('Fehler!!!');
  end else Showmessage('Fehler beim laden der Ant.dll');
end;

function CloseAntDll: Boolean;
begin
  if AntLib <> 0 then
  begin
    ANT_ResetSystem;
     ANT_Nap(1000);
    ANT_Close;
    FreeLibrary(AntLib);
    result := True;
  end else
    result := False;
end;

function RESPONSE_FUNC(ucANTChannel: UCHAR; ucResponseMsgID: UCHAR): Boolean;
var
  i: Integer;
  str: String;
begin
  outputdebugstring(Pchar(Inttohex(ucResponseMsgID, 1)));
  for I := 0 to 9 do
    str := str + ' ' + inttohex(ucResponseBuffer[i], 1);
  outputdebugstring(Pchar(str));
  case ucResponseMsgID of
    MESG_RESPONSE_EVENT_ID:
    begin
      case ucResponseBuffer[MESSAGE_BUFFER_DATA3_INDEX] of
      RESPONSE_NO_ERROR:
        begin
          case ucResponseBuffer[MESSAGE_BUFFER_DATA2_INDEX] of
          MESG_ASSIGN_CHANNEL_ID: begin ANT_SetChannelId(0, 0, 120, 1); OutputDebugString('MESG_ASSIGN_CHANNEL_ID'); end;
          MESG_CHANNEL_MESG_PERIOD_ID: begin ANT_SetChannelRFFreq(0, 57); OutputDebugString('MESG_CHANNEL_MESG_PERIOD_ID'); end;
          MESG_NETWORK_KEY_ID: begin ANT_AssignChannel(0, 0, 0); OutputDebugString('MESG_NETWORK_KEY_ID'); end;
          MESG_CHANNEL_ID_ID: begin ANT_SetChannelPeriod(0, 8070);OutputDebugString('MESG_CHANNEL_ID_ID'); end;
          MESG_CHANNEL_RADIO_FREQ_ID: begin ANT_OpenChannel(0); OutputDebugString('MESG_CHANNEL_RADIO_FREQ_ID'); end;
          end;
        end;
      end;
    end;
  end;
  Result := True;
end;


function CHANNEL_EVENT_FUNC(ucANTChannel: UCHAR; ucEvent: UCHAR): Boolean;
var
  i: Integer;
  str: String;
begin
  outputdebugstring(Pchar(Inttohex(ucEvent, 1)));
  for I := 0 to 16 do
    str := str + ' ' + inttohex(ucChannelBuffer[i], 1);
  outputdebugstring(Pchar(str));
  str := IntToStr(ucChannelBuffer[8]);
  if str <> Form1.lab_Puls.Caption then Form1.lab_Puls.Caption := str;
  Result := True;
end;

end.



Gruß Wal

Geändert von Wal ( 9. Jul 2011 um 12:55 Uhr) Grund: Code eingefügt
  Mit Zitat antworten Zitat
brechi

Registriert seit: 30. Jan 2004
823 Beiträge
 
#6

AW: Hilfe bei einem Callback einer C++ Dll nach Delphi

  Alt 13. Jul 2011, 20:37
Weil der Callback von der DLL aufgerufen wird und dieser in c++ dann eben die Parameter als cdecl uebergibt und Delphi denkt es waere Register? Ich würd ja generell für alle prcoedure stdcall verwenden sowohl in Delphi als auch in c++ wenn du die dll sowieso erstellst.
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:35 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz