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 :

C# DllImport d'une fonction C utlisant un pointeur de char


Sujet :

C#

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2010
    Messages
    15
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2010
    Messages : 15
    Par défaut C# DllImport d'une fonction C utlisant un pointeur de char
    Bonjour à tous,

    J'essaye d'utiliser un SDK permettant d'interagir avec les périphériques d'un réseau ArtNet (protocole de communication DMX via le une couche UDP).

    La librairie est écrite en C et se nomme DongleArtNet.dll et j'aimerais pouvoir utiliser au moins quelques une de ces fonctionnalités en C#.

    Le SDK est inclus dans une application appelé DMX-WorkShop

    Une documentation développeur est fournit ainsi que des exemples, notamment un exemple en visualc++ qui fonctionne très bien avec mon VC++ 6.

    Dans la documentation il est expliqué le cycle de fonctionnement du SDK.
    Il faut commencer par appelé une fonction nommé ArtNetInit dont voici la signature en C :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    extern "C" WORD DLL_MODE ArtNetInit(char* NewIp);
    DLL_MODE étant définit comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    #define DLL_MODE __declspec(dllimport)
    Je ne connais pas grand chose au langage C mais après quelques recherche je suis arrivé à une définition 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
    using System;
    using System.Text;
    using System.Runtime.InteropServices;
    namespace ArtNetWrapper
    {
        public static class Wrapper
        {
            [DllImport("DongleArtNet.dll", EntryPoint = "_ArtNetInit")]
            public static extern int ArtNetInit(StringBuilder ipPtr);
     
            private static String ip = "2.255.255.255";
            private static StringBuilder builder;
            public static void ArtNetInit()
            {
                Wrapper.builder = new StringBuilder(Wrapper.ip);
                int result = Wrapper.ArtNetInit(Wrapper.builder);
            }
        }
    }
    Cela ne fonctionne pas j'ai un message d'erreurs :
    Un appel à la fonction PInvoke 'ArtNetWrapper!ArtNetWrapper.Wrapper::ArtNetInit' a déséquilibré la pile. Cela peut se produire, car la signature PInvoke managée ne correspond pas à la signature cible non managée. Vérifiez que la convention d'appel et les paramètres de la signature PInvoke correspondent à la signature non managée cible.
    Pourtant une fenêtre blanche s'affiche et une icône apparait dans la zone de notification (cette librairie lorsqu'elle est utilisé dans d'autre application comme DMX-WorkShop affiche un SplashScreen et un icône dans la zone de notification à son démarrage) et Windows me demande même de débloquer le Firewall pour mon application (il y a donc bien tentative d'accès au réseau.)

    Visiblement le paramètre ou la valeur de retour de la fonction n'est pas du bon type.

    J'ai essayé de jouer sur le Charset , sur le Marshalling vers des types différents rien n'y fait.

    Plusieurs questions me viennent :

    - Le type C WORD est-il bien un int16 en C# ?

    - Pourquoi le point d'entrée est _ArtNetInit alors que dans le code C elle est déclarée comme ArtNetInit ?

    - Comment passer un type char* C ?

    - Existe-t-il un tableau de correspondances des types non managés C avec les types managés C# ?

    - il y-as t-il une autre solution ( code unsafe mais c'est pas bien ! ou faire un wrapper en C++ avec des types compréhensible pour le marshalling de .net ) ?

    Pour le contexte le protocole DMX permet de commander des projecteurs de toutes sortes (lumière, vidéo, ...) et leurs paramètres (couleurs, rotation ...) il est très utilisé dans le monde du spectacle. Le protocole ArtNet permet de connecter tout ce beau monde sur un réseau informatique et de communiquer avec. On peut imaginer comme application une console lumière virtuel par exemple (bien loin de mes balbutiements).

    Pour moi, je développe en C# ou en Visual BASIC (pas par choix ) des applications très très métiers (gestion des infrastructures autoroutières). Je ne connais presque rien au C ni au C++.

  2. #2
    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
    Salut

    Tout d'abord une grosse erreur a corriger

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    extern "C" WORD DLL_MODE ArtNetInit(char* NewIp);
    Tu ne peux en aucun cas considerer qu'un char *c se traduit en stringbuilder C#

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    [DllImport("DongleArtNet.dll", EntryPoint = "_ArtNetInit")]
            public static extern int ArtNetInit(StringBuilder ipPtr);
    D'apres moi ce serait plutot dans le genre

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
            public static extern int ArtNetInit(IntPtr ipPtr);
    Et Utiliser un Marshall pour transferer ton string ip vers le char *
    Tu peux aussi essayer un bytearray terminé par 0 mais je serais prudent !


    - Le type C WORD est-il bien un int16 en C# ?
    Oui

  3. #3
    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 : 43
    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 champy_dev Voir le message
    - Le type C WORD est-il bien un int16 en C# ?
    Oui, c'est bien un entier sur 16 bits... donc un short, pas un int !
    D'ailleurs un WORD n'est pas signé, donc ce serait même plutôt ushort

    Citation Envoyé par champy_dev Voir le message
    - Comment passer un type char* C ?
    Ca dépend... En général c'est juste une chaine de caractères qui sera seulement lue par la fonction C, dans ce cas tu peux passer un string. Si c'est un buffer dans lequel la fonction C va écrire, tu utilises plutôt un StringBuilder dans lequel tu réserves la capacité nécessaire.

    Dans ton cas, vu qu'il n'y a pas de paramètre pour indiquer la taille du buffer, je pense que c'est simplement une chaine en entrée, donc déclare plutôt le paramètre de type String.

    Mais à mon avis ça devrait fonctionner aussi avec StringBuilder, le problème doit plutôt être causé par le mauvais type de retour.

    Citation Envoyé par champy_dev Voir le message
    - Existe-t-il un tableau de correspondances des types non managés C avec les types managés C# ?


    Citation Envoyé par champy_dev Voir le message
    - il y-as t-il une autre solution ( code unsafe mais c'est pas bien ! ou faire un wrapper en C++ avec des types compréhensible pour le marshalling de .net ) ?
    Un truc comme ça ?
    http://msdn.microsoft.com/en-us/library/ac7ay120.aspx

    Citation Envoyé par olibara Voir le message
    Tu ne peux en aucun cas considerer qu'un char *c se traduit en stringbuilder C#
    Pourquoi tu dis ça ? En C un char * représente (presque toujours) une chaine de caractères. Le marshalling gère automatiquement la conversion avec le type string ou StringBuilder.

    Citation Envoyé par olibara Voir le message
    D'apres moi ce serait plutot dans le genre

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
            public static extern int ArtNetInit(IntPtr ipPtr);
    [/CODE]Et Utiliser un Marshall pour transferer ton string ip vers le char *
    Tu peux aussi essayer un bytearray terminé par 0 mais je serais prudent !
    Ca me semble bien compliqué
    Je suis quasiment certain que ce ne sera pas nécessaire ici

  4. #4
    Membre averti
    Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2010
    Messages
    15
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2010
    Messages : 15
    Par défaut
    Re bonjour,

    J'ai essayé les solutions que vous citez :

    Modifier la signature pour lui passer un pointeur de chaine (cette chaine c'est en fait 2.255.255.255 l'adresse de Broadcast par convention d'un réseau ArtNet), correctement 'Marshaller' , au mois avec tout les cas possible pour une chaine.

    Pour ce qui est du nom de la signature il y a aussi un #define dans le code source C qui li le nom _ArtNetInit à la fonction ArtNetInit. Enfin c'est ce que j'en ai déduis. Dans le doute j'ai essayé les deux sans succès.

    J'ai essayé avec une valeur de retour en int, ushort, short ... sans succès.
    Bien sur j'ai croisé entre elles toutes ces possibilités.

    Mais l'apparition brèves du splashscreen sans son image, l'icone dans la zone de notification et le message du firewall de Windows qui me demande si je veux bien que l'application accède a tel port me laisse penser que la fonction est bien appelé, voir l'IP (la chaine qui est passé en char*) correctement parsée, donc ma valeur bien passer ....

    Lorsque je compile le projet d'exemple livré avec le SDK sous VC++6 dans la console j'ai une phase de recherche de driver ArtNet. Peut-être une piste, des fichiers doivent être présent dans le répertoire de mon application ?

    Bref cela devenant compliqué j'ai pris un peu de recul et avec quelques outils d'analyse de réseaux et les spécifications des paquets j'ai carrément implémenté le protocole pour envoyer des datagrammes UDP.

    Et la ca marche je peux itérer les périphériques du réseau ArtNet, il me renvoi leur description, un début.

    Bon en tout cas merci pour votre aide

    Après est-ce que le post est résolu....

  5. #5
    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 : 43
    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
    Avec ça, ça fonctionne pas ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
            [DllImport("DongleArtNet.dll", EntryPoint = "_ArtNetInit")]
            public static extern ushort ArtNetInit(string ipPtr);

  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
    Bonjour TomLev

    uint16, ushort c'est kif kif !

    Par contre j'ai des sérieux doute sur le casting d'un StringBuilder en char *
    Dans tous les cas ou je devais recuperer le contenu d'un Char * en C je passe par un IntPtr voir un IntPtr ** en unsafe dans le cas on la fonction de ma dll rends un tableau de char *

    Ici c'est un peut different car l'allocation du char * se fait en C#
    C s'attends a interpreter un zstring et je ne vois pas par quelle magie un StringBuilder va se caster en zstring !

Discussions similaires

  1. Réponses: 3
    Dernier message: 16/03/2011, 15h35
  2. Réponses: 6
    Dernier message: 16/01/2011, 15h33
  3. DLL:exporter une fonction qui retourne un pointeur
    Par ephemeride dans le forum C++
    Réponses: 2
    Dernier message: 29/09/2006, 11h42
  4. [Turbo Pascal] Allocation et désallocation de pointeurs dans une fonction
    Par neird dans le forum Turbo Pascal
    Réponses: 13
    Dernier message: 17/11/2002, 20h14
  5. Une fonction avec des attributs non obligatoires
    Par YanK dans le forum Langage
    Réponses: 5
    Dernier message: 15/11/2002, 13h39

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