Probleme DLLIMPORT

garcimor59 Messages postés 66 Date d'inscription mardi 18 juillet 2006 Statut Membre Dernière intervention 6 mars 2008 - 5 mars 2008 à 17:59
Lutinore Messages postés 3246 Date d'inscription lundi 25 avril 2005 Statut Membre Dernière intervention 27 octobre 2012 - 7 mars 2008 à 03:57
Bonjour,

Voilà j'utilise une DLL faite en C (pas sur) dans du code C#, j'ai donc suivit la méthode indiquée dans les differents  posts du forum.
Cela  fonctionne correctement pour 2 fonctions de la  DLL, mais pour une ça ne fonctionne pas.

Voilà le code que j'ai  :

        [DllImport("opdes.dll",  CharSet = System.Runtime.InteropServices.CharSet.Auto)]
        private static extern byte[] OF_MAC
        (
            byte[] MESSAGE
            //       return parameter is a list of 8 bytes;
            //--    MESSAGE : input parameter list of 200_000 bytes
        );

Ma fonction C# qui appelle cette fonction :

 
public static byte[] CBC_MAC(byte[] argMsg, string argKey)
        {
            try
            {
                byte[] KTRANS = HexToByte(argKey);
                OP_INPUT_3KEYS(KTRANS);   //Une des fonctions de la dll qui fonctionne trés bien
                byte[] test = new byte[200000];

                byte[] CYPHER = new byte[8];
                byte[] CYPHER = OF_MAC(test);

                return CYPHER;
            }
            catch { return null; }
        }

Et voilà l'erreur que je récupere dans mon catch :

Impossible de marshaler 'return value' : Combinaison de types managés/non managés non valide.

Auriez-vous une idée du probleme?

Merci pour votre aide.

Cdt,

G.

7 réponses

Lutinore Messages postés 3246 Date d'inscription lundi 25 avril 2005 Statut Membre Dernière intervention 27 octobre 2012 41
5 mars 2008 à 19:14
Salut, c'est toujours un problème ce genre de fonction qui renvoie un tableau.. la valeur de retour ne peut pas être un tableau, ça doit être un IntPtr, ( dans ton cas on pourrait même s'amuser à marshaller en Uint64 soit 8 bytes ). Le problème c'est que le tableau a été alloué dans le code non-managé,  on ne peut plus libérer la mémoire dans le code managé, à moins de disposer d'une fonction genre FREE_OF_MAC( byte[ ] result ) ou avoir utiliser CoTaskMemAlloc du coté non-managé. Tu auras donc peut être ( ou peut être pas ) un mémory leak de 8 bytes à chaque appel de cette fonction. :/
0
garcimor59 Messages postés 66 Date d'inscription mardi 18 juillet 2006 Statut Membre Dernière intervention 6 mars 2008
5 mars 2008 à 21:41
Je suis vraiment désolé mais tu viens de quelle planete? Je comprends pas ta langue!

Lol

Je connais pas trop le IntPtr je vais me renseigner et essayer demain, je vois pas trop comment l'utiliser dans code C#.

J'essai et je vous dis quoi?

Bonne soirée

Merci

G.
0
garcimor59 Messages postés 66 Date d'inscription mardi 18 juillet 2006 Statut Membre Dernière intervention 6 mars 2008
6 mars 2008 à 11:11
Re,

Bon j'ai essayé avec le code suivant :

        [DllImport("opdes.dll",  CharSet = System.Runtime.InteropServices.CharSet.Auto)]
        private static extern IntPtr OF_MAC
        (
            byte[] MESSAGE
            //       return parameter is a list of 8 bytes;
            //--    MESSAGE : input parameter list of 200_000 bytes the first byte is the MSB of length
            //--    the fourth byte is LSB of the length. (first byte always = 0)
            //--    Length is the message length (4 bytes of length not include)
            //--    Length is (0 .. 196_000)
        );

public static byte[] CBC_MAC(byte[] argMsg, string argKey)
        {
            try
            {
                byte[] KTRANS = HexToByte(argKey);
                OP_INPUT_3KEYS(KTRANS);
                byte[] test = new byte[200000];

                byte[] CYPHER = new byte[8];
   
                IntPtr p = OF_MAC(test);
             
                return CYPHER;
            }
            catch { return null; }
        }

Et j'ai l'erreur suivante :

Tentative de lecture ou d'écriture de mémoire protégée. Cela indique souvent qu'une autre mémoire est endommagée.

En cherchant un peu avec l'aide de mon meilleur ami google, j'ai vu qu'il fallait utiliser l'instruction fixed  comme expliqué ici :
http://www.csharpfr.com/infomsg_METTRE-TABLEAU-BYTE-DANS-SYSTEM-INTPTR_874456.aspx

Mais il veut plus compiler parce que je dois compiler avec l'argument /unsafe
Donc je suis la procédure indiquée ici : http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cscomp/html/vclrfunsafeenableunsafemode.asp (version 2005 team suite)

Mais moi, dans Property Pages -> Build -> je n'ai pas de checkbox "Allow Unsafe Code"

Voilà si, si quelqu'un  a une idée, je suis preneur...

Merci

G.
0
Lutinore Messages postés 3246 Date d'inscription lundi 25 avril 2005 Statut Membre Dernière intervention 27 octobre 2012 41
6 mars 2008 à 13:06
En fait soit ta fonction renvoie une référence ( un pointeur ) dans ce cas il faut utiliser un IntPtr puis la méthode Marshal.Copy ( ou le code unsafe )  pour transformer le IntPtr en tableau de bytes soit ta fonction renvoie un "type valeur" et dans ce cas il faut utiliser un Int64 puis la méthode BitConverter.GetBytes.
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
garcimor59 Messages postés 66 Date d'inscription mardi 18 juillet 2006 Statut Membre Dernière intervention 6 mars 2008
6 mars 2008 à 14:04
Je suis pas sur d'avoir compris ce que tu as dis.
En gros, tu m'expliques comment récuperer un tableau de byte selon que la fonction retourne un IntPtr ou un Int64 (si j'ai bien compris :-) )
Bon si c'est ça, je suis ok et je vois comment faire.

Mon probleme c'est que je n'arrive à rien récuperer lors de l'appel de la fonction.
Que ça soit avec un IntPtr ou un Int64 j'ai toujours la meme erreur dans mon catch :

Tentative de lecture ou d'écriture de mémoire protégée. Cela indique souvent qu'une autre mémoire est endommagée.

Voilà, je ne sais plus quoi tester... a votre bon coeur m'sieur dame...

Merci

G.
0
garcimor59 Messages postés 66 Date d'inscription mardi 18 juillet 2006 Statut Membre Dernière intervention 6 mars 2008
6 mars 2008 à 14:21
Au fait merci pour ton aide Lutinore ;-)

Et si j'arrivais à compiler en unsafe ça pourrait peut-etre m'aider...

Wait and see.

Merci

G.
0
Lutinore Messages postés 3246 Date d'inscription lundi 25 avril 2005 Statut Membre Dernière intervention 27 octobre 2012 41
7 mars 2008 à 03:57
Dans Visual Studio clique droit sur ton projet -> propriétés -> Générer -> Autoriser le code unsafe. Ou avec le compilo en ligne de commande option "-unsafe".

Vire le "CharSet.Auto" qui joue peut être des tours.

Autant l'erreur "Impossible de marshaler 'return value' .. " est normale, par contre la seconde "Tentative de lecture ou d'écriture de mémoire protégée .. " là je ne vois pas :/
0
Rejoignez-nous