Dllimport passage de structure en char * [Résolu]

toni93330 9 Messages postés dimanche 19 novembre 2006Date d'inscription 14 février 2009 Dernière intervention - 21 janv. 2009 à 10:38 - Dernière réponse : toni93330 9 Messages postés dimanche 19 novembre 2006Date d'inscription 14 février 2009 Dernière intervention
- 23 janv. 2009 à 09:29
Bonjour,

Voila, je sais qu'il y a pas mal de post sur les dllimport en c#, mais je n'ai pas trouvé ce que je cherche (ou mal ?).

Alors voila j'ai une dll ecrit en C avec des fonctions qui prennent en second paramètre un char * (qui peut être modifié en sortie)
1) Mon problème est comment passé une structure en char * aux fonctions de la dll ?
2) dans certains cas j'ai besoin de passé un champs de la structure dans certaines fonctions, comment faire ?

Voici la déclaration de la structure en c#
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
        public struct SHISDOS
        {
            [MarshalAs(UnmanagedType.ByValTStr   , SizeConst = (int)typesize.LONGSIZE)]
            public string numdos;   /*  1 : numero dossier        */
            [MarshalAs(UnmanagedType.ByValTStr , SizeConst = (int)typesize.LONGSIZE)]
            public string numlig;   /*  2 : numero de ligne        */
            [MarshalAs(UnmanagedType.ByValTStr , SizeConst = (int)typesize.LONGSIZE)]
            public string date;     /*  3 : date                  */
            [MarshalAs(UnmanagedType.ByValTStr , SizeConst = (int)typesize.CHARSIZE * 8)]
            public string opera;    /*  4 : code operation-document */
            [MarshalAs(UnmanagedType.ByValTStr , SizeConst = (int)typesize.CHARSIZE * 28)]
            public string libell; /*C_( libell[2],  28)             5 : 1..2 libelles              */
            [MarshalAs(UnmanagedType.ByValTStr , SizeConst = (int)typesize.CHARSIZE * 28)]
            public string libell2; /*C_( libell[2],  28)             5 : 1..2 libelles              */
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = (int)typesize.DOUBLESIZE * 6)]
            public string[] montan;     /* 20 : 1..6 ht tva exo (Etude)
                             ht tva exo (Debou)    */
            /* 21 : montant ttc             */
            /* 29 : 1..6 ht tva exo (Etude)
       Ex. dispo ht tva exo (Debou)    */
            [MarshalAs(UnmanagedType.ByValTStr , SizeConst = (int)typesize.INTSIZE)]
            public string zondos;     /*  7 : no zone dossier     */
            [MarshalAs(UnmanagedType.ByValTStr , SizeConst = (int)typesize.CHARSIZE * 3)]
            public string collab;     /*  8 : code collaborateur    */
            [MarshalAs(UnmanagedType.ByValTStr , SizeConst = (int)typesize.CHARSIZE)]
            public string typhis;        /*  9 : type d'historique    */
            /*     O : Operation comptable    */
            /*     C : Courrier        */
            /*     A : Acte        */
            /*    I : Calcul d'interet    */
            /*    S : Message Serveur    */
            /*    T : appel telephonique    */
            /*    V : rendez-vous        */
            [MarshalAs(UnmanagedType.ByValTStr , SizeConst = (int)typesize.CHARSIZE * 10)]
            public string destin;             /* 10 : destinataire /banque    */
            [MarshalAs(UnmanagedType.ByValTStr , SizeConst = (int)typesize.CHARSIZE)]
            public string gestio;             /* 11 : Supp/Regu/Mult/Blanc    */
            [MarshalAs(UnmanagedType.ByValTStr , SizeConst = (int)typesize.CHARSIZE)]
            public string marque;             /* 12 : marquage utilisateur    */
            [MarshalAs(UnmanagedType.ByValTStr , SizeConst = (int)typesize.INTSIZE)]
            public string tpspas;             /* 13 : temps passe        */
            [MarshalAs(UnmanagedType.ByValTStr , SizeConst = (int)typesize.INTSIZE)]
            public string kilome;             /* 14 : kilometres parcourus    */
            [MarshalAs(UnmanagedType.ByValTStr , SizeConst = (int)typesize.CHARSIZE)]
            public string determ;             /* 15 : action determinante o/n    */
            [MarshalAs(UnmanagedType.ByValTStr , SizeConst = (int)typesize.CHARSIZE * 3)]
            public string ctitre;             /* 16 : code titre        */
            [MarshalAs(UnmanagedType.ByValTStr , SizeConst = (int)typesize.LONGSIZE)]
            public string numfac;             /* 17 : numero de facture    */
            [MarshalAs(UnmanagedType.ByValTStr , SizeConst = (int)typesize.LONGSIZE)]
            public string numgrp;             /* 18 : numero de groupe     */
            [MarshalAs(UnmanagedType.ByValTStr , SizeConst = (int)typesize.INTSIZE)]
            public string numtva;             /* 19 : indice tva              */
            [MarshalAs(UnmanagedType.ByValTStr , SizeConst = (int)typesize.LONGSIZE)]
            public string datcpt;             /* 25 : date de comptabilisation*/
            [MarshalAs(UnmanagedType.ByValTStr , SizeConst = (int)typesize.CHARSIZE)]
            public string devise;             /* 26 : monnaie: F=francs,E=euro*/
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = (int)typesize.DOUBLESIZE * 3)]
            public string[] valdev;          /* 27 : valeur devise ht,tva,exo*/
            [MarshalAs(UnmanagedType.ByValTStr , SizeConst = (int)typesize.LONGSIZE)]
            public string numrec;             /* 28 : numero de reçu       */
            [MarshalAs(UnmanagedType.ByValTStr , SizeConst = (int)typesize.LONGSIZE)]
            public string facture;             /* 31 : numero de facture       */
        }

et la declaration  fonction :
        [DllImport("xxxdll.dll")]
         static extern unsafe  int readfic(int handle, [MarshalAs(UnmanagedType.ByValTStr )] string destination, int mode);
        [DllImport("xxxdll.dll")]
        unsafe static extern void stdbl(double value,  [MarshalAs(UnmanagedType.ByValTStr )] string destination);

en C les declarations des fonctions :
  extern "C" int readfic( int handle, char *buf, int mode);
  extern "C" void stdbl(double, char *buf);

J'ai tout essayé mais pas réussi a faire marché .
Pouvez-vous m'aidé  ?

Merci
Afficher la suite 

Votre réponse

4 réponses

Lutinore 3248 Messages postés lundi 25 avril 2005Date d'inscription 27 octobre 2012 Dernière intervention - 22 janv. 2009 à 17:15
+3
Utile
Oui c'est plus clair..

Dans ta struct c'est bien des tableaux inlines donc ta définition semble correct, il faut marshaller chaque champs par une string avec ByValTStr , SizeConst, le CharSet.Ansi de ta struct est correct aussi.. par contre le Pack= 1 il n'a pas lieu d'être là sauf si dans le code C/C++ il y a un #pragma pack de défini.

Si ça plante encore, essaye de remplacer les strings de la struct par des bytes ( 1 octet et sans zéro à la fin donc ). Les classes genre ASCIIEncoding etc.. permettent de concevertir des chaines en tableau de bytes.

pour la fonction :




[ StructLayout( LayoutKind.Sequential ) ]
private struct UnmanagedStruct
{
    [ MarshalAs( UnmanagedType.ByValArray, SizeConst = 4 ) ]
    public byte[ ] param0;
    [ MarshalAs( UnmanagedType.ByValArray, SizeConst = 4 ) ]
    public byte[ ] param1;
}





[ DllImport( "xxx.dll" ) ]
private static extern void UnmanagedFunc( ref UnmanagedStruct st );





private void ManagedFunc( )
{
    UnmanagedStruct st;
    st.param0 = new byte[ ] { 1, 2, 3, 4 };
    st.param1 = new byte[ ] { 4, 3, 2, 1 };
    UnmanagedFunc( ref st );
}




ou en version unsafe ( rapide car sans marshalling ) :




[ StructLayout( LayoutKind.Sequential ) ]
private unsafe struct UnmanagedStruct
{
    public fixed byte param0[ 4 ];
    public fixed byte param1[ 4 ];
}





[ DllImport( "xxx.dll" ) ]
// ou void* pour passer aussi l'adresse d'un élément.
// ou une surcharge qui prend un byte*.
private static extern unsafe void UnmanagedFunc( UnmanagedStruct* st );





private unsafe void ManagedFunc( )
{
    UnmanagedStruct st; // sur la pile.
    st.param0[ 0 ] = 0;
    st.param1[ 0 ] = 0; // etc..
    UnmanagedFunc( &st );
}
Cette réponse vous a-t-elle aidé ?  
Commenter la réponse de Lutinore
Lutinore 3248 Messages postés lundi 25 avril 2005Date d'inscription 27 octobre 2012 Dernière intervention - 21 janv. 2009 à 17:00
0
Utile
Salut, je vois pas la définition en C de ta struct.. après c'est pas clair si tes fonctions C attendent une chaine de caractères ou une struct.

char* c'est un pointeur sur une chaine ANSI, ce qui correspond en code managé à un simple paramètre "string" + CharSet=CharSet.Ansi.

je vois que tu utilises bcp ByValTStr, mais c'est reservé pour les tableaux de caractères "inline" et pas pour les pointeurs sur char.
Commenter la réponse de Lutinore
toni93330 9 Messages postés dimanche 19 novembre 2006Date d'inscription 14 février 2009 Dernière intervention - 22 janv. 2009 à 07:38
0
Utile
Bonjour,

voici la structure en C:
typedef struct {
    char numdos[4];       
    char  numlig[4];          
    char date[4];            
    char opera[8];            
    char  libell[2][ 28];          
    char  montan[6][8];                                            
    char  zondos[2];            
    char  collab[3];            
    char  typhis[1];       
    char  destin[10]           
    char  gestio[1];            
    char  marque[1];          
    char tpspas[2];            
    char kilome[2];           
    char  determ[1];           
    char ctitre[ 3];           
    char  numfac[11];           
    char numgrp [4];            
    char numtva[2];           
    char datcpt[4];           
    char  devise[1];           
    char  valdev[3][8]);    
    char  numrec [ 4];          
    char facture[4];           
} SHISDOS;

la structure représente un enregistrement  dans un fichier, ce fichier est de type c-isam donc toutes les fonctions de la dll prennent en char * en entrée En gros on a en C
isread(handle, (char *)&shisdos, 0);
Chaque champs de la structure n'est pas terminé par un 0, donc c'est reellement un tableau.
Voila, est-ce plus claire ?
Commenter la réponse de toni93330
toni93330 9 Messages postés dimanche 19 novembre 2006Date d'inscription 14 février 2009 Dernière intervention - 23 janv. 2009 à 09:29
0
Utile
Bonjour,

Merci, cela marche en utilisant la dernière méthode.
Commenter la réponse de toni93330

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.