Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Hilfe bei einem Callback einer C++ Dll nach Delphi (https://www.delphipraxis.net/161533-hilfe-bei-einem-callback-einer-c-dll-nach-delphi.html)

Wal 7. Jul 2011 16:10

Hilfe bei einem Callback einer C++ Dll nach Delphi
 
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

DeddyH 8. Jul 2011 08:15

AW: Hilfe bei einem Callback einer C++ Dll nach Delphi
 
Müssten die beiden Callback-Funktionen nicht auch als cdecl deklariert werden?

Wal 8. Jul 2011 15:20

AW: Hilfe bei einem Callback einer C++ Dll nach Delphi
 
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.

Wal 9. Jul 2011 12:21

AW: Hilfe bei einem Callback einer C++ Dll nach Delphi
 
Liste der Anhänge anzeigen (Anzahl: 1)
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.

Wal 9. Jul 2011 12:50

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

Zitat von DeddyH (Beitrag 1110741)
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

brechi 13. Jul 2011 20:37

AW: Hilfe bei einem Callback einer C++ Dll nach Delphi
 
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.


Alle Zeitangaben in WEZ +1. Es ist jetzt 21:58 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