PDA

View Full Version : [C#] P/invoke di callback methods


DuHarTapt
09-12-2008, 13:12
C
typedef void (*mia_uno)(int a);

extern "C" __declspec(dllexport) void create(classe1 a1, mia_uno b2)
{
// fa quel che deve fare
}


C#

delegate void mia_uno(int a);
[DllImport("test.dll")]
internal static extern void create(IntPtr a1, mia_uno b2 );

IntPtr ptr; // viene inizializzato altrove

private void testing()
{
mia_uno delMia = new miaDel(funccall);
create(ptr, delMia);
}

private void funcall(int i)
{
Console.WriteLine("ciao" + i.toString());
}




Ho sbagliato qualcosa?

Tutto questo genera "Eccezione win32 non gestita". :confused:
In msdn ho trovato che l'istanza del delegate deve coprire il tempo di vita del codice unmanaged. Potrebbe essere questo il problema?
Come si fa a fare ciò?

gugoXX
09-12-2008, 13:55
Prova a lasciar fare il lavoro al Maresciallo.
Ovvero non passare un IntPtr ad una zona unmanaged, costruisci la versione di "classe1" anche in C#, sempre se puoi (meglio struttura che classe anche qui se puoi), creane l'istanza, popola e passala alla create.
Il Maresciallo della Interop dovrebbe occuparsi della copia (per quello dico piu' sicura la struttura che non la classe per riferimento)

Prova anche a racchiudere la chiamata di testing in un try-catch e leggere l'eventuale innerException sperando di trovar qualcosa di piu' di una generica "Eccezione non gestita"

DuHarTapt
09-12-2008, 14:34
main()
{
try
{
testing();
}
catch(Exception e){ Console.Write(e.toString();}
Console.Read();
}

facendo il debug l'eccezione viene generata dopo Console.Read().
Se tolgo Console.Read() viene generata dopo l'ultima parentesi } :confused:



Ovvero non passare un IntPtr ad una zona unmanaged, costruisci la versione di "classe1" anche in C#, sempre se puoi (meglio struttura che classe anche qui se puoi), creane l'istanza, popola e passala alla create.

Purtroppo sono costretto ad utilizzare IntPtr.
Il problema è il passaggio delle funzioni di callback, che vengono richiamate più volte. Se passo "null" funziona tutto, quindi penso il problema sia quello.

:)