Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (WinAPI, Konsole) » callback function pointer

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: > 1 < [ 2 ]
000
24.08.2008, 11:44 Uhr
sojahulk



hallo,

ich versuche verzweifelt mit meinen rudimentären c++ fähigkeiten eine dll zu programmieren, mir eine function aus einer anderen dll mit einer callbackfucktion ausführt.

folgendes habe ich geschreieben:

C++:
#include "stdafx.h"
#include "types.h"

#include "antdefines.h"
#include "antmessage.h"
#include "ant_dll.h"


P_ANT_ARF         ANT_AssignResponseFunction;
P_ANT_AEF         ANT_AssignChannelEventFunction;
P_ANT_SHM          ANT_SerialHaveMessage;


static HMODULE hANTdll;
static BOOL bLoaded = FALSE;

   UCHAR ucChannel;

BOOL ANT_Load(void)
{
   if (bLoaded)
      return TRUE;

   hANTdll = LoadLibraryA("ANT_DLL.dll");
   if (hANTdll == NULL)
      return FALSE;

   ANT_AssignResponseFunction = (P_ANT_ARF) GetProcAddress(hANTdll, "ANT_AssignResponseFunction");
   ANT_AssignChannelEventFunction = (P_ANT_AEF) GetProcAddress(hANTdll, "ANT_AssignChannelEventFunction");
   ANT_SerialHaveMessage = (P_ANT_SHM) GetProcAddress(hANTdll, "ANT_SerialHaveMessage");

   if (ANT_AssignResponseFunction == NULL)
      return FALSE;
   if (ANT_AssignChannelEventFunction == NULL)
      return FALSE;
   if (ANT_SerialHaveMessage == NULL)
      return FALSE;

   bLoaded = TRUE;
   return TRUE;
}

void ANT_UnLoad(void)
{
   if (hANTdll != NULL)
   {
      FreeLibrary(hANTdll);
   }
   bLoaded = FALSE;
}

UCHAR* SerialRawData(UCHAR ucChannel, UCHAR *pucRxBuffer)
{
ANT_AssignResponseFunction( (RESPONSE_FUNC)ANT_SerialHaveMessage,aucResponseBuf );
ANT_AssignChannelEventFunction(ucChannel, (CHANNEL_EVENT_FUNC)ANT_SerialHaveMessage, pucRxBuffer );
return pucRxBuffer;
}



als bsp: die event funkiton ist wie folgt aufgebaut:


C++:
//in der .h definierter functionpointer
typedef BOOL (*CHANNEL_EVENT_FUNC)(UCHAR ucANTChannel, UCHAR ucEvent);
//

void ANT_AssignChannelEventFunction(UCHAR ucLink, CHANNEL_EVENT_FUNC pfLinkEvent, UCHAR *pucRxBuffer)
{
   sLink[ucLink].pfLinkEvent = pfLinkEvent;
   sLink[ucLink].pucRxBuffer = pucRxBuffer;
}



und der linkevent wir hier behandelt:

C++:
void ANT_SerialHaveMessage(void)
{
   UCHAR aucData[MESG_RSSI_DATA_SIZE];
   UCHAR ucSize;
   UCHAR ucID;
   UCHAR ucANTChannel;

   //If no response function has been assigned, ignore the message and unlock
   //the receive buffer
   if (pfResponseFunc == NULL)
   {
      Serial_ClearState(SERIAL_STATE_RX_BUFFER_LOCK);    // unlock RX buffer
      return;
   }

   ucSize = Serial_GetMesg(&ucID, &aucData[0]);

   ucANTChannel = aucData[MESG_CHANNEL_OFFSET] & CHANNEL_NUMBER_MASK;

   //Process the message to determine whether it is a response event or one
   //of the channel events and call the appropriate event function.
   switch (ucID)
   {
      case MESG_RESPONSE_EVENT_ID:
         if (aucData[MESG_EVENT_ID_OFFSET] != MESG_EVENT_ID) // this is a response
         {
            if (pucResponseBuffer)
            {
               memcpy(pucResponseBuffer, &aucData[0], MESG_RESPONSE_EVENT_SIZE);
               pfResponseFunc(ucANTChannel, MESG_RESPONSE_EVENT_ID);
            }
         }
         else // this is an event
         {
            // If we are in auto transfer mode, stop sending packets
            if ((aucData[MESG_EVENT_CODE_OFFSET] == EVENT_TRANSFER_TX_FAILED) && (ucAutoTransferChannel == ucANTChannel))
               usNumDataPackets = 0;

            if (sLink[ucANTChannel].pfLinkEvent == NULL)
               break;

            memcpy(sLink[ucANTChannel].pucRxBuffer, &aucData[0], ucSize);
            sLink[ucANTChannel].pfLinkEvent(ucANTChannel, aucData[MESG_EVENT_CODE_OFFSET]); // pass through any events not handled here
         }
         break;

      case MESG_BROADCAST_DATA_ID:
         if (sLink[ucANTChannel].pfLinkEvent == NULL)
            break;

         //Call channel event function with Broadcast message code
         memcpy(sLink[ucANTChannel].pucRxBuffer, &aucData[0], MESG_DATA_SIZE);
         sLink[ucANTChannel].pfLinkEvent(ucANTChannel, EVENT_RX_BROADCAST);                 // process the event
         break;
.
.
.




ich wäre sehr dankbar für hilfe, und auch bereit zu zahlen, wenn sich jemand dieser aufgabe annehmen möchte.

thanx
hulk
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
24.08.2008, 12:27 Uhr
xXx
Devil


Wo ist denn jetzt konkret dein Problem?
Ich denk mal, das deine ANT_-Funktionen als C++ gebuildet wurden? Dann sind die Namensgebungen nicht so wie in C (extern "C" hilft) und können nicht so einfach geladen werden. Um das zu überprüfen kannste einfach mal Dependency Walker nehmen und gucken wie die Funktionen heißen.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
26.08.2008, 12:04 Uhr
sojahulk



hallo,

vorab mal danke fürs helfen.. aber mein problem ist konkret, dass ich leider den umgang mit den callback funktionen nicht checke. (bin leider kein guter, wenn überhaupt programmierer).

ich möchte ja eigentlich nix anderes tun, als die daten die im *pucRxBuffer stehen auslesen.
ich habe es versucht wie in der dokumentation zu machen (http://www.thisisant.com/index.php?module=resourcesmodule&src=@random43c2ebc53db95) aber ich bring das einfach nicht zusammen.

vorgestellt hätte ich es mir so, dass ich die assignchanneleventfunction aus der herstellerdll lade, sie mit der callbackfunktion versorge und mir den zeiger auf den pucRxBuffer zurückgeben lasse.

-- soweit so gut -- aber wie schaut die callbackfunktion denn nun aus?

danke im voraus für alle tipps
hulk
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
26.08.2008, 17:04 Uhr
xXx
Devil


Nja erstmal würde ich das ganze auf Klassen umbauen.

Eine DLL bekommt ein Klasseninterface:
Library.hpp

C++:
#if !defined (LIBRARY_HPP__INCLUDED)
#define LIBRARY_HPP__INCLUDED

#pragma once

#include <windows.h>

namespace winapipp
{
    struct Library
    {
        Library(std::string const& file)
            : m_module(::LoadLibraryA(file.c_str()))
        {
            if (!m_module) throw std::invalid_argument("invalid library file");
        }
        
        virtual ~Library()
        {
            ::FreeLibrary(m_module);
        }

    protected:
        template<typename function_type>
        inline function_type load_function(std::string const& name)
        {
            function_type temp(static_cast<function_type>(::GetProcAddress(m_module, name.c_str())));
            if (temp == NULL) throw std::invalid_argument("unknown function specifier");
            return temp;
        }
    
    private:
        ::HMODULE m_module;
    };
}; // winapipp

#endif // LIBRARY_HPP__INCLUDED

so, jetzt brauchen wir uns nicht mehr um die Arbeit auf WinAPI-Ebene kümmern, sondern das übernimmt die Klasse, z.B. könnte man so etwas laden (Funktion void foo(); aus der DLL "sample.dll"):


C++:
typedef void (*fnFoo)(void); // function pointer typedef

int main()
{
    try {
        Library sample("sample.dll"); // versuchen zu laden
        fnFoo foo_function(sample.load<fnFoo>("foo")); // versuchen funktion zu laden
    } catch (std::invalid_argument const& ex) // wenn es nicht geht wird ne exception geworfen
    { std::cerr << ex.what() << std::endl; } // fehler ausgeben
}
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
004
26.08.2008, 18:12 Uhr
Guybrush Threepwood
Gefürchteter Pirat
(Operator)


Wenn man Klassen in DLLs verpackt sollte man allerdings darauf achten das der Export nicht standatisiert ist und man diese dann ggf. mit einer anderen Entwicklungsumgebung (oder Version der Selben) nicht verwenden kann.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
005
26.08.2008, 22:07 Uhr
xXx
Devil


? Das ist eine Klasse, um DLLs zu laden
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
006
27.08.2008, 09:29 Uhr
Guybrush Threepwood
Gefürchteter Pirat
(Operator)


Ah ok, hab nur den Text ohne Quellcode gelesen
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
007
28.08.2008, 15:58 Uhr
sojahulk



hallo,

vorab mal - danke für die antworten.

aber das laden der dll funktioniert ja ohne probleme. ich hab nur leider keine ahnung wie meine callback funktion aussehen soll.

die dll (des herstellers) macht folgendes


C++:
void ANT_AssignChannelEventFunction(UCHAR ucLink, CHANNEL_EVENT_FUNC pfLinkEvent, UCHAR *pucRxBuffer)
{
   sLink[ucLink].pfLinkEvent = pfLinkEvent;
   sLink[ucLink].pucRxBuffer = pucRxBuffer;
}



und den link über diese funktion


C++:

void ANT_SerialHaveMessage()
{
   UCHAR aucData[MESG_RSSI_DATA_SIZE];
   UCHAR ucSize;
   UCHAR ucID;
   UCHAR ucANTChannel;

   //If no response function has been assigned, ignore the message and unlock
   //the receive buffer
   // if (pfResponseFunc == NULL)
   //{
   //   Serial_ClearState(SERIAL_STATE_RX_BUFFER_LOCK);    // unlock RX buffer
   //   return;
   //}
        
   ucSize = Serial_GetMesg(&ucID, &aucData[0]);

   ucANTChannel = aucData[MESG_CHANNEL_OFFSET] & CHANNEL_NUMBER_MASK;

   //Process the message to determine whether it is a response event or one
   //of the channel events and call the appropriate event function.
   switch (ucID)
   {
      case MESG_RESPONSE_EVENT_ID:
         if (aucData[MESG_EVENT_ID_OFFSET] != MESG_EVENT_ID) // this is a response
         {
            if (pucResponseBuffer)
            {
               memcpy(pucResponseBuffer, &aucData[0], MESG_RESPONSE_EVENT_SIZE);
               pfResponseFunc(ucANTChannel, MESG_RESPONSE_EVENT_ID);
            }
         }
         else // this is an event
         {
            // If we are in auto transfer mode, stop sending packets
            if ((aucData[MESG_EVENT_CODE_OFFSET] == EVENT_TRANSFER_TX_FAILED) && (ucAutoTransferChannel == ucANTChannel))
               usNumDataPackets = 0;

            if (sLink[ucANTChannel].pfLinkEvent == NULL)
               break;

            memcpy(sLink[ucANTChannel].pucRxBuffer, &aucData[0], ucSize);
            sLink[ucANTChannel].pfLinkEvent(ucANTChannel, aucData[MESG_EVENT_CODE_OFFSET]); // pass through any events not handled here
         }
         break;
...
...
...



die callbackfunktion - mit der ich die ant_assignchanneleventfunction in miener dll ausführen möchte soll laut der beschreibung so aussehen:


C++:
bool channel_event_funct(UCHAR ucChannel, UCHAR ucEvent)
{
   Switch (ucEvent)
     {
      Case EVENT_RX_BROADCAST: // PC applications only; use MsgID 0x4E in embedded
      Switch (ucChannel)
         {
         Case Channel_0:
        // process received data which is in channel event buffer - WAS KOMMT HIER NUR  REIN???!!!???
         Break;
         ..
        }
       Break;
      }

}



was muss meine event function nun tun damit die hersteller dll mir die daten, die mir des wireless modul schick in den buffer schreibt und ich ihn auslesen kann..?

bitte leute, lasst mich nicht dumm sterben - aus mir wird sicher nie ein programmiere werden..

thanx
martin
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
008
28.08.2008, 16:36 Uhr
Guybrush Threepwood
Gefürchteter Pirat
(Operator)


Du musst das nicht in den Buffer schreiben sondern das steht da schon drin

Das heißt hier

C++:
Case Channel_0:
        // process received data which is in channel event buffer - WAS KOMMT HIER NUR  REIN???!!!???
         Break;



stehen die Daten die der Sensor schickt in der Variable die du ANT_AssignChannelEventFunction als 2. Parameter übergeben hast.

Dieser Post wurde am 28.08.2008 um 16:37 Uhr von Guybrush Threepwood editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
009
28.08.2008, 21:26 Uhr
~sojahulk_
Gast


hallo,

danke für die antwort. aber nun bin ich echt verwirrt... denn sollte dann dieser code nicht funktionieren?


C++:
#include "stdafx.h"
#include "types.h"

#include "antdefines.h"
#include "antmessage.h"
#include "callbackwrapper.h"


//////////////////////////////////////////////////////////////////////////////////
// Public Variables
//////////////////////////////////////////////////////////////////////////////////

// Function Pointers
P_ANT_ARF         ANT_AssignResponseFunction;
P_ANT_AEF         ANT_AssignChannelEventFunction;
UCHAR aucChannelEventBuffer[MESG_DATA_SIZE];
UCHAR aucResponseBuffer[MESG_RESPONSE_EVENT_SIZE];


//////////////////////////////////////////////////////////////////////////////////
// Private Variables
//////////////////////////////////////////////////////////////////////////////////
static HMODULE hANTdll;
static BOOL bLoaded = FALSE;
UCHAR ucChannel;


//////////////////////////////////////////////////////////////////////////////////
// Public Functions
//////////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////
extern "C" __declspec(dllexport) BOOL ANT_Load(void)
{
   if (bLoaded)
      return TRUE;

   hANTdll = LoadLibraryA("ANT_DLL.dll");
   if (hANTdll == NULL)
      return FALSE;

   ANT_AssignResponseFunction = (P_ANT_ARF) GetProcAddress(hANTdll, "ANT_AssignResponseFunction");
   ANT_AssignChannelEventFunction = (P_ANT_AEF) GetProcAddress(hANTdll, "ANT_AssignChannelEventFunction");

   if (ANT_AssignResponseFunction == NULL)
      return FALSE;
   if (ANT_AssignChannelEventFunction == NULL)
      return FALSE;

   bLoaded = TRUE;
   return TRUE;
}

///////////////////////////////////////////////////////////////////////
extern "C" __declspec(dllexport) void ANT_UnLoad(void)
{
   if (hANTdll != NULL)
   {
      FreeLibrary(hANTdll);
   }
   bLoaded = FALSE;
}

///////////////////////////////////////////////////////////////////////
BOOL ChannelEventFunction(UCHAR ucChannel, UCHAR ucEvent)
{
    switch (ucEvent)
        {
        case EVENT_RX_BROADCAST:
            switch (ucChannel)
            {
                case 0:
                // process received data which is in channel event buffer
                break;
                case 1:
                // process received data which is in channel event buffer
                break;
                case 2:
                // process received data which is in channel event buffer
                break;
            }    
            return (TRUE);
            break;
        }
    return (FALSE);
}
      

extern "C" __declspec(dllexport)void ANT_EVENT(UCHAR ucChannel, UCHAR* aucRxBuf)
{
ANT_AssignChannelEventFunction(ucChannel,&ChannelEventFunction, aucRxBuf);
}
BOOL ResponseFunction(UCHAR ucChannel, UCHAR ucMessageCode)
{
   switch (ucMessageCode)
   {
      case MESG_CHANNEL_STATUS_ID:
      switch (aucResponseBuffer[1]) // channel status
        {
            
            case 0:
            // channel is un-assigned
                break;
            case 1:
            // channel is assigned
                break;
        }
      return (TRUE);
   }
   return (FALSE);
}

extern "C" __declspec(dllexport)void ANT_RESPONSE(UCHAR ucChannel, UCHAR* aucResponseBuffer)
{
        ANT_AssignResponseFunction(&ResponseFunction,aucResponseBuffer);
}



oder besser gefragt - wieso funktioniert diese wrapper dll nicht?

danke im voraus für die hilfe (denn ohne dieses forum hätte ich schon längst die flinte ins korn geworfen)

thanx
martin
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: > 1 < [ 2 ]     [ C / C++ (WinAPI, Konsole) ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: