2012-05-31 22 views
5

Ho recentemente lavorato su C# a C++, in particolare impostando una funzione di callback chiamata DLL C++.C# C++ callback dell'interoperazione

namespace TomCSharpDLLImport 
{ 
    class Program 
    { 
     public delegate void TomDelegate(int a, int b); 

     [DllImport("TomDllNative.dll", CallingConvention = CallingConvention.Cdecl)] 
     public static extern void GetData(); 

     [DllImport("TomDllNative.dll", CallingConvention = CallingConvention.Cdecl)] 
     public static extern void SetCallback(TomDelegate aCallback); 

     static void Main(string[] args) 
     { 
      TomDelegate lTD = new TomDelegate(Program.TomCallback); 

      SetCallback(lTD); //Sets up the callback 

      int thread = Thread.CurrentThread.ManagedThreadId; 

      GetData(); //This calls the callback in unmanaged code 

      while (true) ; 
     } 

     //Callback function which is called from the unmanaged code 
     public static void TomCallback(int a, int b) 
     { 
      Console.WriteLine("A: {0} B: {1}", a, b); 
      int thread = Thread.CurrentThread.ManagedThreadId; 
     } 
    } 
} 

La domanda che ho è che, quando il controllo del programma entra in funzione TomCallback, mi aspettavo che poi ha colpito il (vero) ciclo while in Main. Tuttavia, invece, il programma è appena uscito. Non riesco a capire il comportamento, una parte di me immagina che questo sia come previsto ma una parte di me si sarebbe aspettata che continuasse in main.

quello che mi aspettavo ...

  1. La funzione GetData() viene chiamato
  2. La funzione GetData chiama la callback
  3. La funzione di callback ritorna al GetData
  4. GetData ritorna al main()

Tuttavia, questo non è giusto.

Sarebbe qualcuno abbastanza gentile da spiegare cosa succede.

Al fine di risparmiare spazio non ho postato il codice non gestito, ma se è necessario sono felice di inviare

Edit: ho acceso il debug non gestito (totalmente dimenticato di farlo) e ora vedo lo schianto ..

Errore in fase di esecuzione # 0 - Il valore di ESP non è stato salvato correttamente attraverso una chiamata di funzione. Questo di solito è il risultato del richiamo di una funzione dichiarata con una convenzione di chiamata con un puntatore di funzione dichiarato con una convenzione di chiamata diversa.

codice nativo come questo è dove incidente è

#include "stdafx.h" 
typedef void (*callback_function)(int, int); 

extern "C" __declspec(dllexport) void SetCallback(callback_function aCallback); 
extern "C" __declspec(dllexport) void GetData(); 

callback_function gCBF; 

__declspec(dllexport) void SetCallback(callback_function aCallback) 
{ 
    gCBF = aCallback; 
} 

__declspec(dllexport) void GetData() 
{ 
    gCBF(1, 2); 
} 

risposta

11

È necessario convertire il callback riuscito al puntatore a funzione Native (IntPtr in C#) con il metodo

IntPtr Marshal.GetFunctionPointerForDelegate(Delegate d) 

.

L'utilizzo di SetCallback() con System.Delegate come argomento è errato.

Make it

SetCallback(Marshal.GetFunctionPointerForDelegate(lTD)); 

e ridichiarare SetCallback come

/// StdCall is crucial here 
[DllImport("TomDllNative.dll", CallingConvention = CallingConvention.StdCall)] 
public static extern void SetCallback(IntPtr aCallback); 
+0

Hi Viktor, Grazie per la risposta. Ho apportato le modifiche come suggerito, ma mostra ancora esattamente lo stesso comportamento. – TomP89

+0

Il programma "termina" - questo significa un arresto anomalo. Saresti così gentile da mostrare la discarica? Questo può essere fatto nello strumento Visualizzatore eventi, nell'elenco Errori applicazione. Oppure copia l'opzione della console del tuo programma. –

+0

Grazie Viktor, ho aggiornato la domanda – TomP89

Problemi correlati