Callback in C++
-
Hallo,
ich schreibe gerade an einer kleinen DLL die über einen Callback Mechanismus mit einer C# Anwendung kommunizieren soll. Dabei gehe ich so vor:
Von der C# Anwendung aus rufe ich folgende Funktion auf und übergebe die Adresse der aufzurufenden Funktion:
int SetCallback(void(*Callback)(int)) { return port.SetCallbackFunction(Callback); }port.SetCallbackFunction(Callback) macht folgendes:
int CANPort::SetCallbackFunction(void (*Callback)(int)) { this->CallbackFunction = Callback; return (int)Callback; }Den Funktionszeiger habe ich in der Klasse folgendermaßen deklariert:
void(*CallbackFunction)(int);Den CallbackMechanismus möchte ich dann mit folgender Funktion durchführen:
if (this->CallbackFunction != NULL) (*CallbackFunction)(pRdObj->Channel+1);Leider bekomme ich immer Zugriffsverletzungen. Die Adresse der C# Funktion übergebe ich folgendermaßen an die ganz oben genannte SetCallback Funktion in der C++ DLL:
IntPtr procCallbackAdr = GetProcAddress(m_dllHandle, "SetCallback"); SetCallbackDelegate setCallbackDel = (SetCallbackDelegate)Marshal.GetDelegateForFunctionPointer(procCallbackAdr, typeof(SetCallbackDelegate)); CallbackFunctionDelegate internCallbackFunction = new CallbackFunctionDelegate(this.DriverCallbackFunction); IntPtr callbackPointer =Marshal.GetFunctionPointerForDelegate(internCallbackFunction); int rV = setCallbackDel(callbackPointer);Ich bin mir ziemlich sicher das der Fehler irgendwo im C++ Code hängt und habe mich deshalb für das Forum hier entschieden.
Weiß jemand wo der Fehler liegt? Ich finde ihn einfach nicht, habe schon zig Quellen nach Callback Mechanismen durchsucht und komme leider auf keine Lösung.
-
Dein C#-Code sagt mir leider nichts.
Spontan fällt mir bloß ein, dass die calling convention vielleicht nicht stimmt. Sowas wie __cdecl oder __stdcall.Stefan.
-
Wenn ich mir deinen C# Quellcode anschaue, dann habe ich eher das Gefühl, dass dieser das Problem ist. Wie kannst du so sicher sein, dass es am C++ Code liegen soll?
Zum Beispiel habe ich seeeeeehr starke Zweifel, dass du als Callback eine nicht statische Memberfunktion angeben kannst. Auch deine Cast sind für mich zum Teil etwas verwirrend und ich habe so meine Zweifel, dass dort dies passiert, was du möchtest.Woher hast du dieses Vorgehen? Selber zusammengedacht oder aus einem Tutorial? Such mal auf www.codeproject.com, dort gibt es sicher ein paar Erklärung, wie man solche Callbacks durchführt. Ansonsten würde ich eher mal im C# Forum nachfragen

Grüssli
-
Hier mal ein kleines Bsp:
Edit
Anmerkung: Bei deinem Code scheint mir einiges schief, desshalb habe ich nicht den Code korrigiert, sondern eben dieses Bsp. gemacht.DLL Code:
#include "stdafx.h" #include <windows.h> #include <tchar.h> extern "C" { typedef void (__stdcall *Callback)(int); Callback _callback = 0; void __stdcall SetCallback(Callback callback) { OutputDebugString(_T("SetCallback(..)\r\n")); _callback = callback; } void __stdcall TestCallback(int value) { OutputDebugString(_T("TestCallback(..)\r\n")); if (0 != _callback) { _callback(value); } } }Zugehöriges *.def File um die Funktionen zu exportieren.
(Kann natürlich auch anders exportiert werden)LIBRARY "Lib" EXPORTS SetCallback TestCallbackC# Applikation:
using System; using System.Runtime.InteropServices; namespace App { class Program { delegate void Callback(int value); [DllImport(@"..\..\..\debug\Lib.dll")] static extern void SetCallback(Callback callback); [DllImport(@"..\..\..\debug\Lib.dll")] static extern void TestCallback(int value); static void Main(string[] args) { Callback callback = new Callback(OnCallback); SetCallback(callback); TestCallback(12); SetCallback(null); } static void OnCallback(int value) { Console.WriteLine("OnCallback(..), value = " + value); } } }Ich hoffe es hilft Dir weiter.
Simon