Delegatinstanz bei CallBack Pointer
-
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());
-
Noch eine kleine Fehlerquelle.
Der GC weiß nichts von nativen Funktionszeigern und gibt das delegate frei für den Mülleimer.
Um das zu verhindern musst Du entweder immer eine managed referenz auf das Objekt halten (z.B. in der Klasse als member) oder aber mit GCHandle::Allocate() und Free() selbst eine managed referenz "erzeugen".Grüße
Viel Spaß noch