IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C# Discussion :

interopérabilité C / C#


Sujet :

C#

  1. #1
    Invité(e)
    Invité(e)
    Par défaut interopérabilité C / C#
    Bonjour,

    Dans le cadre de mon travail, j'ai réalisé une DLL windows dont toute l'interface est en C. À priori (ce n'est pas moi qui l'utilise en C#), il est tout à fait possible d'appeler des fonctionS C depuis le C#.

    Une des fonctions de cette DLL C utilise un système de callback : on enregistre à un moment une fonction que la DLL appellera toute seule le moment venu.

    Le prototype du callback ressemble à
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void __stdcall mon_callback(void*, size_t, size_t, int);
    Du coup, comment, en C#, déclarer (ou définir) une méthode (ou une fonction) pour que son prototype et sa convention d'appel soit compatible avec le prototype C donné ?

    Merci

    mabu

  2. #2
    Expert confirmé

    Homme Profil pro
    Chef de projet NTIC
    Inscrit en
    Septembre 2006
    Messages
    3 580
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Chef de projet NTIC
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Septembre 2006
    Messages : 3 580
    Par défaut
    salut

    il faut que tu regardes du coté de l'interopérabilité et les mécanismes
    P/Invoke

  3. #3
    Membre expérimenté
    Profil pro
    Mangeur de gauffre
    Inscrit en
    Octobre 2007
    Messages
    4 413
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Mangeur de gauffre

    Informations forums :
    Inscription : Octobre 2007
    Messages : 4 413
    Par défaut
    Un truc du genre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
        [DllImport("MaDll.Dll")]
        static public extern void mon_callback(ref IntPtr ptr, int a, int sz,int b);
    Note l'usage de ref IntPtr ptr pour emuler ton void *

    Je ne garranti pas le truc a 100% c'est généralement là qu'il faut touiller un peu en fonction de l'usage interne qui est fait de ce pointeur

    Attention aussi aux size_t : j'ai mis int mais ca dépends de ton environnement c'est peut etre int64 !

  4. #4
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Par défaut
    Citation Envoyé par olibara Voir le message
    Note l'usage de ref IntPtr ptr pour emuler ton void *
    Pas besoin du ref, IntPtr est suffisant

  5. #5
    Invité(e)
    Invité(e)
    Par défaut
    Merci pour vos réponses.

    Je ne vais pouvoir tester vos suggestions tout de suite, mais dès que ça sera fait, je reviendrai vous dire comment ça se passe.

    Merci encore

  6. #6
    Membre expérimenté
    Profil pro
    Mangeur de gauffre
    Inscrit en
    Octobre 2007
    Messages
    4 413
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Mangeur de gauffre

    Informations forums :
    Inscription : Octobre 2007
    Messages : 4 413
    Par défaut
    Pas besoin du ref, IntPtr est suffisant
    Pas forcément !

    Tout dépends de la maniere dont ce void* est traité dans la dll
    S'il est modifié c'est un ** et le ref devient nécessaire

    (j'ai eu le cas)

  7. #7
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Par défaut
    Citation Envoyé par olibara Voir le message
    Pas forcément !

    Tout dépends de la maniere dont ce void* est traité dans la dll
    S'il est modifié c'est un ** et le ref devient nécessaire

    (j'ai eu le cas)
    ben dans ce cas c'est la signature C qui n'est pas correcte... ça devrait être un void** il me semble (mais bon, ça fait longtemps que j'ai pas fait du C...)

  8. #8
    Invité(e)
    Invité(e)
    Par défaut
    Alors en fait, en c ça se passe comme ça :

    le client de la DLL écrit un fonction genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    void __stdcall callback_client(void* data, size_t data_size, size_t foo, int bar)
    {
        /* le client travaille avec les data créés par la DLL */
        printf("les data sont :%s", data);
    }
    Le client ne modifie pas les data, il ne fait que les recevoir à intervalle régulier.

    Il enregistre cette fonction auprès de la DLL :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    DLL_enregistreCallBack(callback_client);
    Et c'est la DLL qui va appeler (dans un thread séparé) la fonction du client quand des datas seront prêt.

    Ma question porte donc sur : comment écrire une fonction C# pour pouvoir la donner en paramètre à ma fonction DLL_enregistreCallBack ?

  9. #9
    Membre expérimenté
    Profil pro
    Mangeur de gauffre
    Inscrit en
    Octobre 2007
    Messages
    4 413
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Mangeur de gauffre

    Informations forums :
    Inscription : Octobre 2007
    Messages : 4 413
    Par défaut
    ben dans ce cas c'est la signature C qui n'est pas correcte... ça devrait être un void**
    Tu a raison c'est moi qui me suis basé sur un mauvais exemple !

    Par le jeu des typedef en C on finit par faire passer une vache pour un cochon !

    Donc pour mabu c'est bien un IntPtr qu'il faut passer et pas un ref IntPtr

  10. #10
    Membre expérimenté
    Profil pro
    Mangeur de gauffre
    Inscrit en
    Octobre 2007
    Messages
    4 413
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Mangeur de gauffre

    Informations forums :
    Inscription : Octobre 2007
    Messages : 4 413
    Par défaut
    Ma question porte donc sur : comment écrire une fonction C# pour pouvoir la donner en paramètre à ma fonction DLL_enregistreCallBack ?
    Ouille !

    Maintenant je comprends le problème et je serais tres curieux de voir s'il y a une solution

  11. #11
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Par défaut
    Il faut déclarer un delegate avec une signature qui correspond :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    delegate void MonCallback(IntPtr data, int data_size, int foo, int bar);

  12. #12
    Invité(e)
    Invité(e)
    Par défaut Youpi ça fonctionne
    Impec, ça a l'air de marcher à merveille...

    Dans mon code je mixe donc du
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    delegate void LE_Callback(char* data, UInt32 data_size, UInt32 foo, Int32 bar);
     
    [DllImport("madll.Dll")]
    static extern int DLL_enregistreCallback(LE_Callback func);
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void mon_callback(char *pImage, UInt32 size, UInt32 foo, Int32 bar) 
    {
        /* ... */
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    LE_Callback callback = new LE_Callback(this.mon_callback);
    DLL_enregistreCallback(callback );
    Cela dit, la convention d'appel du c# a l'air d'être du stdcall puisse que si je me passe du delegate, le tout ne m'explose pas à la figure :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    static void mon_callback(char *pImage, UInt32 size, UInt32 foo, Int32 bar) 
    {
        /* ... */
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    DLL_enregistreCallback(mon_callback);
    EDIT
    le tout unsafe bien sur
    /EDIT

    un grand
    Dernière modification par Invité(e) ; 10/02/2009 à 16h36.

  13. #13
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Par défaut
    Citation Envoyé par mabu Voir le message
    Cela dit, la convention d'appel du c# a l'air d'être du stdcall
    Tu peux choisir la convention d'appel avec le champ CallingConvention de l'attribut DllImport

  14. #14
    Invité(e)
    Invité(e)
    Par défaut
    Citation Envoyé par tomlev Voir le message
    Tu peux choisir la convention d'appel avec le champ CallingConvention de l'attribut DllImport
    Bon à savoir.

    Une question par curiosité, y-a-t-il moyen de modifier la convention d'appel des fonctions écrites en c#. Aujourd'hui, la DLL c appelle ma fonction c# et tout se passe bien, mais que ce serait il passé si ma DLL attendait un cdecl ?

  15. #15
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Par défaut
    tu dois pouvoir utiliser UnmanagedFunctionPointerAttribute, qui semble être le pendant de DllImportAttribute pour les délégués... (je m'en suis jamais servi, je viens de découvrir son existence dans la doc )

  16. #16
    Membre expérimenté
    Profil pro
    Mangeur de gauffre
    Inscrit en
    Octobre 2007
    Messages
    4 413
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Mangeur de gauffre

    Informations forums :
    Inscription : Octobre 2007
    Messages : 4 413
    Par défaut
    Et bien je trouve que ce sujet est particulierement instructif !

    Meci a mabu de l'avoir ouvert et a TomLev d'avoir si bien trouvé les réponses adéquates !

Discussions similaires

  1. [Interopérabilité] Problème d'interfaçage fortran/C
    Par afrancisco dans le forum Fortran
    Réponses: 0
    Dernier message: 18/10/2007, 11h07
  2. [C++\CLI] Interopérabilité COM
    Par Ll_Gailin24px dans le forum C++/CLI
    Réponses: 6
    Dernier message: 20/07/2007, 09h47
  3. interopérabilité entre OCAML et C!
    Par slider22 dans le forum Caml
    Réponses: 3
    Dernier message: 25/06/2007, 01h51
  4. Réponses: 4
    Dernier message: 17/10/2006, 15h01
  5. Interopérabilité .Net/Java problème des Hearder Soap
    Par broidsy dans le forum Services Web
    Réponses: 2
    Dernier message: 31/07/2006, 10h31

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