Delegatinstanz bei CallBack Pointer
-
Hallo!
Ich erstelle gerade eine Wrapper-dll um einige Funktionen einer anderen DLL zu Kapseln. Die DLL soll ein Fenster erzeugen indem der User später die gewünschte Hardware auswählen kann. Das Aufrufen der Fenster klappt mittlerweile, jedoch komme ich bei der Übergabe eines FuncPointer zu einer CallBack Funktion nicht weiter. Der Pointer muss an eine aus der "gewrappten"-DLL befindlichen Funktion übergeben werden, hier erst mal der code...:
header datei der "gewrappten" dll:
typedef void (__stdcall *RECEIVE_CALLBACK)(ESACAN_MSG *msg, int reply);
main.h
#pragma once #include "StdAfx.h" #include "SelectNetworkDialog.h" using namespace CANopenWrapper; using namespace System; ref class main { public: main(void); void goCANopen(void); void go(void); void __stdcall ReceiveMessage(ESACAN_MSG *msg, int reply); private: SelectNetworkDialog myDialog; };
main.cpp
#include "StdAfx.h" #include "main.h" #include "resource.h" extern "C" __declspec(dllexport)void go(void); // hardware handle to use #define HWHANDLE 16 // PCAN-USB // maximum networks we support #define MAX_NETWORKS 100 ...... USW USW USW USW andere code....... // register callback function for messages Event_Receive(&main::ReceiveMessage ); ...... USW USW USW USW andere code....... void __stdcall main::ReceiveMessage ( XXXXX_MSG *msg, // message received int reply // set to 1 if message is a reply to message txed ) { myDialog.txtFeld->Text += (String)msg->id; myDialog.txtFeld->Text += (L"RX: id=0x%8.8lX, dlc=%d, data=0x%2.2X 0x%2.2X 0x%2.2X 0x%2.2X 0x%2.2X 0x%2.2X 0x%2.2X 0x%2.2X\n", msg->id, msg->dlc,msg->data[0], USW USW USW }
Aus rechtlichen gründen musste ich leider einige teile XXXen bzw rausnehmen...
DIe Fehlermeldung die nun auftritt ist:
1>.\main.cpp(75) : error C3374: Adresse von "main::ReceiveMessage" kann nur übernommen werden, wenn eine Delegatinstanz erstellt wird
Zeile 75 ist:
Event_Receive(&main::ReceiveMessage );
hat jemand eine konkreten Lösungsvorschlag? Ich hab bereits mehrere dinge mit "deligate" erfolglos probiert...
-
Event_Receive(&main::ReceiveMessage );
Was soll denn damit erreicht werden?
Ich sehe nirgends eine Dekl. od. Def. von Event_Receive.Simon
-
oh ok, das steht auch in der header datei deklariert:
ESACANOPENPRO_API void __stdcall Event_Receive(RECEIVE_CALLBACK Func);
-
#define ESACANOPENPRO_API extern C __declspec(dllimport)
-
Mach Dir doch einen Delegate (meinDelegate) und übergib ihn dann so:
IntPtr myPtr = Marshal::GetFunctionPointerForDelegate(meinDelegate); meineNativeFunktionMitCallbakParamter(myPtr.ToPointer());
Musst nur aufpassen, dass du einen managed handle auf Dein delegate hälst, sonst wird das delegate für den GC freigegeben.
Etwas knapp! Trotzdem klar?
-
danke templäd!
ich hab jezt:
myPtr = System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(&main::ReceiveMessage); Event_Receive((RECEIVE_CALLBACK)myPtr.ToPointer());
allerdings meckert er dabei immer noch, aber n über was anderes...
pingeliger compiler..;)1>.\main.cpp(76) : error C3374: Adresse von "main::ReceiveMessage" kann nur übernommen werden, wenn eine Delegatinstanz erstellt wird.
-
void __stdcall ReceiveMessage(ESACAN_MSG *msg, int reply);
Die Methode ist nicht statisch. Das bedeutet, dass Du eine Instanz haben musst.
Oder Du machst die Methode statisch.Simon
-
sollte das nicht dadurch gemacht werden :?
myPtr = System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(&main::ReceiveMessage);
-
Mach "ReceiveMessage" static!
-
auch mit einer static ReceiveMessage:
1>.\main.cpp(76) : error C3374: Adresse von "main::ReceiveMessage" kann nur übernommen werden, wenn eine Delegatinstanz erstellt wird
:((
-
Zeig den Code.
-
Du hast kein Delegat.
1. Delegat definieren
2. Delegat instanzieren und mit main::Receove... binden.Hast Du mal geschaut was Marshal::GetFunctionPointerForDelegate(..) als Parameter verlangt?
Kein Funktions Pointer, sondern (hat der Kompiler schon gesagt) ein Delegaten Objekt.Simon
-
"Delegate": genau das ist doch hier die Frage, wie erzeuge ich so ein delegate korrekt. Und als mögliche Lösung wurde GetFunctionPointerForDelegate vorgeschlagen, jezt soll ich dafür wieder delegate erzeugen? ein delegate für das delegate damit ich ein delegate erzeugen kann?
Der gesamte Quellcode kann aus lizentechnischen Gründen (Einbindundung lizensierter Code-Teile) nicht vollständig gepostet werden
templäd schrieb:
Mach Dir doch einen Delegate (meinDelegate) und übergib ihn dann so:
IntPtr myPtr = Marshal::GetFunctionPointerForDelegate(meinDelegate); meineNativeFunktionMitCallbakParamter(myPtr.ToPointer());
Musst nur aufpassen, dass du einen managed handle auf Dein delegate hälst, sonst wird das delegate für den GC freigegeben.
Etwas knapp! Trotzdem klar?
-
Hat noch jemand einen Vorschlag wie ich das Problem löse?
-
mach doch ein mini bsp. und zeige dann diesen code hier.
simon
-
das ist es...
main.h
#pragma once #include "StdAfx.h" #include "SelectNetworkDialog.h" using namespace CANopenWrapper; using namespace System; void goCANopen(void); delegate void ReceiveMessage(CAN_MSG *msg, int reply); ref class main { public: main(void); void go(void); //void __stdcall ReceiveMessage(CAN_MSG *msg, int reply); static void __clrcall ReceiveMessage(CAN_MSG *msg, int reply); private: //SelectNetworkDialog myDialog; };
main.c
#include "StdAfx.h" #include "main.h" #include "resource.h" using namespace System; using namespace System::Runtime::InteropServices; extern "C" __declspec(dllexport)void go(void); //delegate how2: http://msdn.microsoft.com/de-de/library/ms235575.aspx main::main(void) { } // hardware handle to use #define HWHANDLE 16 // PCAN-USB // maximum networks we support #define MAX_NETWORKS 100 void main::go() { //myDialog.txtFeld->Text = "hallo"; // myDialog.txtFeld->Text += " welt"; // myDialog.ShowDialog(); goCANopen(); } void goCANopen() { // CANopenWrapper::SelectNetworkDialog myDialog = new CANopenWrapper::SelectNetworkDialog::SelectNetworkDialog(); // register callback function for messages //Event_Receive(&main::ReceiveMessage ); //myPtr = System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(&main::ReceiveMessage); //Event_Receive((RECEIVE_CALLBACK)myPtr.ToPointer()); ReceiveMessage^ callback = gcnew ReceiveMessage(main::ReceiveMessage); //delegate ^d = gcnew delegate(myMain, &main::ReceiveMessage); Event_Receive(callback); //Event_Receive(System::Runtime::InteropServices::Marshal::GetDelegateForFunctionPointer(&main::ReceiveMessage)); myDialog.txtFeld->Text +=(L"Waiting 10 seconds for messages to arrive\n"); } //void __stdcall main::ReceiveMessage void __clrcall main::ReceiveMessage ( CAN_MSG *msg, // message received int reply // set to 1 if message is a reply to message txed ) { //myDialog.txtFeld->Text += (String)msg->id; }
Es soll also zum einen ein CALLBack Pointer an die ReceiveMessage(externe dll) Funktion übergeben werden, zum anderen ein Window erzeugt werden in dem die Daten angezeigt (bzw später ausgewählt -> dropDown) werden können.
-
Auf die Schnelle...
Sind alles Zeilen aus Deinem code nur die Reihenfolge der Aufrufe war ein bißchen verschobendelegate ^d = gcnew delegate(myMain, &main::ReceiveMessage); //das geht falls die methode nicht statisch ist myPtr = System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(d); Event_Receive((RECEIVE_CALLBACK)myPtr.ToPointer()); // Event_Receive(callback);
-
Funktioniert das auch zur Laufzeit???
static void __clrcall ReceiveMessage(CAN_MSG *msg, int reply);
Ich kann doch nicht aus nativen code einen clrcall machen oder?
Gibt's da ne compiler magic ???
-
clrcall: keine ahnung ob das so geht, ich hatte erst stdcall daraufhin hat der compiler empfohlen clccall zu verwenden (als warning..)
hab deine reihenfolge getestet, allerdings.....
1>.\main.cpp(88) : error C2065: 'delegate': nichtdeklarierter Bezeichner
"del" statt "delegate geht ebenfalls nicht...
Ich verwende MS C++ Express 2008 (kein MFC)
-
Naja aber das muss man schon wissen. Delegate^ schreibt man groß und für das zweite kleine Delegate musst du das verwenden , das du mit...
delegate void ReceiveMessage(CAN_MSG *msg, int reply); // würde ich besser anders nennen //z.B. ReceiveMessageDel weiß nicht ob es sonst Namenskonflikte gibt.
definiert hast.
Also so:
Delegate ^d = gcnew ReceiveMessageDel(myMain, &main::ReceiveMessage); //das geht falls die methode nicht statisch ist myPtr = System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(d); Event_Receive((RECEIVE_CALLBACK)myPtr.ToPointer());
-
Danke an alle für die Mithilfe! Ein Programmierer allein würde elendige sterben.
Die Lösung sieht wie jetzt wie folgt aus:
CanWrapper^ myCanWrapper = gcnew CanWrapper; myReceiveMessageDelegate^ d = gcnew myReceiveMessageDelegate(myCanWrapper, &CanWrapper::ReceiveMessage); //das geht falls die methode nicht statisch ist myPtr = System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(d); Event_Receive((RECEIVE_CALLBACK)myPtr.ToPointer());