Bonjour...
j'ai décidé de réinventer l'eau chaude dans le but d'avoir une meilleur compréhension de C#.
J'utilise Flight Simulator de Microsoft, je programme en C# pour mon loisir.
Je souhaite créer un programme tier qui sera en communication avec mon simulateur.
A ce jour, il existe une libraire SimConnect qui permet de dialoguer avec un programme externe (ou module) et le simulateur. Il y a aussi sa variante en DotNet (écrite en C++/CLR selon ILSpy).
J'aime la simplicité et je souhaiterai fabriquer ma propre version managée.
Microsoft nous propose son SDK pour Flight Simulator, donc j'ai le fichier "simconnect.h", ainsi que sa DLL native.
Mais voila, dans cette fabuleuse histoire (qui devrait se terminer par une fin heureuse), j'ai un problème, un problème de pointeur (enfin un truc de ce genre que l'on ne voit que très très rarement en C#)...
Voici donc le code issu de "simconnect.h" :
Et pour les curieux :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12 #if !defined(SIMCONNECTAPI) #define SIMCONNECTAPI extern "C" HRESULT __stdcall #endif typedef void (CALLBACK *DispatchProc)(SIMCONNECT_RECV* pData, DWORD cbData, void* pContext); SIMCONNECTAPI SimConnect_Open(HANDLE * phSimConnect, LPCSTR szName, HWND hWnd, DWORD UserEventWin32, HANDLE hEventHandle, DWORD ConfigIndex); SIMCONNECTAPI SimConnect_Close(HANDLE hSimConnect); SIMCONNECTAPI SimConnect_CallDispatch(HANDLE hSimConnect, DispatchProc pfcnDispatch, void * pContext); SIMCONNECTAPI SimConnect_GetNextDispatch(HANDLE hSimConnect, SIMCONNECT_RECV ** ppData, DWORD * pcbData);
DWORD du type UInt32 (si je ne me trompe pas, selon Google)
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7 struct SIMCONNECT_RECV { DWORD dwSize; // record size DWORD dwVersion; // interface version DWORD dwID; // see SIMCONNECT_RECV_ID };
Voici en C# :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 [StructLayout(LayoutKind.Sequential, Pack = 1)] public class SIMCONNECT_RECV { public UInt32 dwSize; // record size public UInt32 dwVersion; // interface version public UInt32 dwID; // see SIMCONNECT_RECV_ID } public delegate void DispatchProc(SIMCONNECT_RECV [] pData, UInt32 cbData, IntPtr pContext); [DllImport(_libraryName)] internal static extern UInt32 SimConnect_Open(out IntPtr phSimConnect, string szName, IntPtr hWnd, DWORD UserEventWin32, IntPtr hEventHandle, DWORD nfigIndex);// DWORD -> UInt32 [DllImport(_libraryName)] internal static extern UInt32 SimConnect_CallDispatch(IntPtr hSimConnect, DispatchProc proc, IntPtr pContext); [DllImport(_libraryName)] internal static extern unsafe UInt32 SimConnect_GetNextDispatch(IntPtr hSimConnect,/*SIMCONNECT_RECV*/void ** ppData, DWORD* pcbData); // Brut de fonderie [DllImport(_libraryName)] internal static extern UInt32 SimConnect_Close(IntPtr hSimConnect);
Bon,
j'arrive à créer une communication entre le simulateur et mon programme par SimConnect_Open. Je récupère son handle "phSimConnect". Je réussi à fermer la com par SimConnect_Close.
Maintenant, j'ai besoin de traiter les "messages" que m'envoit le simulateur. Pour cela, je dois utiliser SimConnect_CallDispatch et une fonction de même signature que DispatchProc.
Donc, voici mon code (certe pas exceptionnel)
PS : Windows.HResult reprend juste les constantes de HResult... (Nécessaire ou pas, ce n'est pas le problème)
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 protected DispatchProc CallBackReceiveMessage; protected void ReceiveMessage(SIMCONNECT_RECV[] pData, UInt32 cbData, IntPtr pContext) { // Todo } protected void CallDispatch() { unsafe { CallBackReceiveMessage = new DispatchProc(ReceiveMessage); if (NativeUnsafeMethods.SimConnect_CallDispatch(_handleSimConnect, CallBackReceiveMessage, IntPtr.Zero) == Windows.HResult.E_FAIL) { } } }
Quand je compile mon programme, j'ai, comme exception, un vilain petit dialecte venu du moyen-age (Visual Studio de MS) :
Donc voila mon problème sachant que j'ai une énorme ALLERGIE envers les pointeurs et autres membres de leurs familles (car ils sont partout).Assistant Débogage managé 'FatalExecutionEngineError' *:
'Le runtime a rencontré une erreur irrécupérable. L'adresse de l'erreur était 0x5bc96989 sur le thread 0x42c. Le code d'erreur est 0xc0000005. Il s'agit peut-être d'un bogue dans le CLR ou dans les portions unsafe ou non vérifiables du code utilisateur. Les causes courantes de ce bogue incluent des erreurs de marshaling utilisateur pour COM-Interop ou PInvoke, erreurs susceptibles d'endommager la pile.'
J'aimerai découvrir une solution fort simple à mon problème et SURTOUT de comprendre la complexité de conversion entre c, c++ et c# - pointeur (...).
Merci pour votre aide,
Cordialement
Partager