1. #1
    Membre du Club
    Profil pro
    Inscrit en
    mai 2006
    Messages
    43
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : mai 2006
    Messages : 43
    Points : 50
    Points
    50

    Par défaut Convertir une DLL native C en c#,fonction callback

    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" :

    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);
    Et pour les curieux :
    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
    };
    DWORD du type UInt32 (si je ne me trompe pas, selon Google)

    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)
    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)
                    {
     
                    }
                }
            }
    PS : Windows.HResult reprend juste les constantes de HResult... (Nécessaire ou pas, ce n'est pas le problème)

    Quand je compile mon programme, j'ai, comme exception, un vilain petit dialecte venu du moyen-age (Visual Studio de MS) :

    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.'
    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).
    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

  2. #2
    Membre du Club
    Profil pro
    Inscrit en
    mai 2006
    Messages
    43
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : mai 2006
    Messages : 43
    Points : 50
    Points
    50

    Par défaut

    Salut...

    Mon problème venait de la définition du delegate DispatchCall :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
            public delegate void DispatchProc(SIMCONNECT_RECV [] pData, UInt32 cbData, IntPtr pContext);
    SIMCONNECT_RECV[] pData doit devenir SIMCONNECT_RECV pData...

    Voila.

    Bonne journée

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Utilisation d'une dll native par une toolbar managée
    Par didierll dans le forum C++/CLI
    Réponses: 1
    Dernier message: 10/07/2007, 07h56
  2. [C# 2.0] Utilisation d'un IntPtr par une dll native
    Par SesechXP dans le forum C++/CLI
    Réponses: 5
    Dernier message: 05/07/2007, 15h00
  3. Réponses: 2
    Dernier message: 26/06/2007, 17h46
  4. Problème lors de l'import d'une dll native.
    Par -Jolan- dans le forum C++/CLI
    Réponses: 4
    Dernier message: 21/02/2007, 12h18
  5. Réponses: 2
    Dernier message: 28/05/2006, 11h34

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo