Dllimport passage de structure en char *

Résolu
toni93330 Messages postés 9 Date d'inscription dimanche 19 novembre 2006 Statut Membre Dernière intervention 14 février 2009 - 21 janv. 2009 à 10:38
toni93330 Messages postés 9 Date d'inscription dimanche 19 novembre 2006 Statut Membre Dernière intervention 14 février 2009 - 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

4 réponses

Lutinore Messages postés 3246 Date d'inscription lundi 25 avril 2005 Statut Membre Dernière intervention 27 octobre 2012 41
22 janv. 2009 à 17:15
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 );
}
3
Lutinore Messages postés 3246 Date d'inscription lundi 25 avril 2005 Statut Membre Dernière intervention 27 octobre 2012 41
21 janv. 2009 à 17:00
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.
0
toni93330 Messages postés 9 Date d'inscription dimanche 19 novembre 2006 Statut Membre Dernière intervention 14 février 2009
22 janv. 2009 à 07:38
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 ?
0
toni93330 Messages postés 9 Date d'inscription dimanche 19 novembre 2006 Statut Membre Dernière intervention 14 février 2009
23 janv. 2009 à 09:29
Bonjour,

Merci, cela marche en utilisant la dernière méthode.
0
Rejoignez-nous