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++/CLI Discussion :

Passage de paramètres


Sujet :

C++/CLI

  1. #1
    Membre averti
    Inscrit en
    Décembre 2006
    Messages
    23
    Détails du profil
    Informations forums :
    Inscription : Décembre 2006
    Messages : 23
    Par défaut Passage de paramètres
    Bonjour tout le monde,

    Dans la dll non managée, j'ai une fonction qui initialise une structure. J'ai donc crée une classe C# qui se rapporte à cette structure et se compose comme suit:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    [StructLayout(LayoutKind.Sequential)]
    public class ManagedClass
    {
        [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 525420)]
        public byte[] imgData;
        public Int32 imgWidth;
        public Int32 imgHeight;
        public Single imgResolution;
        public sbyte fingerRank;
        public Int32 st;
    }
    Et lorsque j'exécute le code suivant, je constate qu'il y a des différences de valeur à certains indices entre le tableau de bytes que je passe en parametre et celui de ma classe managée.

    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
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    [DllImport(@"DllName.dll", EntryPoint = "Init", SetLastError = true)]
    public static extern IntPtr Init(byte[] raw, int width, int height, Single resolution, int rank, int type);
     
    static void Main(string[] args)
    {
        Bitmap bmp= new Bitmap(@"Image.bmp");
        byte[] raw = GetBytes(bmp);
        IntPtr ptr = new IntPtr();
        ManagedClass mc = new ManagedClass();
     
        ptr = Init(raw, bmp.Width, bmp.Height, 500, 3, 111);
        Marshal.PtrToStructure(ptr, mc);
        int i = 0;
        foreach (byte b in mc.imgData)
        {
            if (b != raw[i])
            {
                string str = string.Format("{0:000} \t {1:000} à l'indice {2}", b, raw[i], i);
                Debug.WriteLine(str);
            }
            i++;
     
        }
    }
     
    private static byte[] GetBytes(Bitmap bmp)
    {
        MemoryStream ms = new MemoryStream();
        bmp.Save(ms, ImageFormat.Bmp);
        byte[] b = ms.GetBuffer();
        return b;
    }
    Voici les différences relevées :
    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
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    246 	 076 à l'indice 0
    003 	 004 à l'indice 1
    073 	 080 à l'indice 9
    110 	 114 à l'indice 10
    116 	 110 à l'indice 12
    070 	 116 à l'indice 13
    105 	 081 à l'indice 14
    110 	 117 à l'indice 15
    103 	 097 à l'indice 16
    101 	 108 à l'indice 17
    114 	 105 à l'indice 18
    112 	 116 à l'indice 19
    114 	 121 à l'indice 20
    105 	 058 à l'indice 21
    110 	 069 à l'indice 22
    116 	 082 à l'indice 23
    073 	 082 à l'indice 24
    109 	 058 à l'indice 25
    097 	 032 à l'indice 26
    103 	 073 à l'indice 27
    101 	 110 à l'indice 28
    058 	 112 à l'indice 29
    069 	 117 à l'indice 30
    082 	 116 à l'indice 31
    082 	 032 à l'indice 32
    058 	 115 à l'indice 33
    032 	 116 à l'indice 34
    084 	 114 à l'indice 35
    104 	 117 à l'indice 36
    101 	 099 à l'indice 37
    032 	 116 à l'indice 38
    105 	 117 à l'indice 39
    110 	 114 à l'indice 40
    112 	 101 à l'indice 41
    117 	 032 à l'indice 42
    116 	 105 à l'indice 43
    032 	 115 à l'indice 44
    104 	 032 à l'indice 45
    101 	 110 à l'indice 46
    105 	 111 à l'indice 47
    103 	 116 à l'indice 48
    104 	 032 à l'indice 49
    116 	 105 à l'indice 50
    032 	 110 à l'indice 51
    115 	 116 à l'indice 53
    032 	 105 à l'indice 54
    119 	 097 à l'indice 55
    104 	 108 à l'indice 56
    101 	 105 à l'indice 57
    116 	 122 à l'indice 58
    104 	 101 à l'indice 59
    101 	 100 à l'indice 60
    114 	 046 à l'indice 61
    032 	 010 à l'indice 62
    117 	 000 à l'indice 63
    110 	 000 à l'indice 64
    100 	 000 à l'indice 65
    101 	 000 à l'indice 66
    114 	 000 à l'indice 67
    032 	 000 à l'indice 68
    050 	 000 à l'indice 69
    053 	 000 à l'indice 70
    054 	 000 à l'indice 71
    032 	 000 à l'indice 72
    119 	 000 à l'indice 73
    104 	 000 à l'indice 74
    101 	 000 à l'indice 75
    116 	 000 à l'indice 76
    104 	 000 à l'indice 77
    101 	 000 à l'indice 78
    114 	 000 à l'indice 79
    032 	 000 à l'indice 80
    111 	 000 à l'indice 81
    118 	 000 à l'indice 82
    101 	 000 à l'indice 83
    114 	 000 à l'indice 84
    032 	 000 à l'indice 85
    052 	 000 à l'indice 86
    048 	 000 à l'indice 87
    057 	 000 à l'indice 88
    054 	 000 à l'indice 89
    046 	 000 à l'indice 90
    010 	 000 à l'indice 91
    067 	 080 à l'indice 159
    111 	 114 à l'indice 160
    109 	 105 à l'indice 161
    109 	 110 à l'indice 162
    111 	 116 à l'indice 163
    110 	 081 à l'indice 164
    070 	 117 à l'indice 165
    117 	 097 à l'indice 166
    110 	 108 à l'indice 167
    099 	 105 à l'indice 168
    105 	 121 à l'indice 170
    111 	 046 à l'indice 171
    110 	 099 à l'indice 172
    115 	 112 à l'indice 173
    046 	 112 à l'indice 174
    099 	 000 à l'indice 175
    112 	 000 à l'indice 176
    112 	 000 à l'indice 177
    097 	 223 à l'indice 412
    Quelqu'un peut-il éclairer ma lanterne sur ce problème SVP???
    Merci d'avance!!!

  2. #2
    Membre éclairé
    Inscrit en
    Juillet 2007
    Messages
    357
    Détails du profil
    Informations forums :
    Inscription : Juillet 2007
    Messages : 357
    Par défaut
    a moins que tu en ai vraiment besoin , enlever les attribut

    [StructLayout(LayoutKind.Sequential)]
    et

    [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 525420)]

    et reteste

  3. #3
    Membre averti
    Inscrit en
    Décembre 2006
    Messages
    23
    Détails du profil
    Informations forums :
    Inscription : Décembre 2006
    Messages : 23
    Par défaut
    Je ne sais pas si j'en ai absolument besoin, mais si je ne les mets pas, j'ai des exceptions qui sont soulevées.

    pour la piste.

  4. #4
    Membre éclairé
    Inscrit en
    Juillet 2007
    Messages
    357
    Détails du profil
    Informations forums :
    Inscription : Juillet 2007
    Messages : 357
    Par défaut
    tu peux toujours essayer ca

    cree une structure

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    public struct ManagedStruct
    {
        public byte[] imgData;
        public Int32 imgWidth;
        public Int32 imgHeight;
        public Single imgResolution;
        public sbyte fingerRank;
        public Int32 st;
    }
    une autre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    public struct ManagedStruct_tempon
    {
        public Intptr imgData;
        public Int32 imgWidth;
        public Int32 imgHeight;
        public Single imgResolution;
        public sbyte fingerRank;
        public Int32 st;
    }
    [/CODE]



    ensuite dans ton code

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    ManagedStruct l_ms;
    l_ms.imdData = new byte[525420];
    ManagedStruct_tempon l_ms_tempon ;
    IntPtr ptr = IntPtr.zero;
    ptr = Init(raw, bmp.Width, bmp.Height, 500, 3, 111);
    Marshal.PtrToStructure(ptr, l_ms_tempon);
    Marshal.Copy( ManagedStruct_tempon.imgData, ManagedStruct.imgData, 
    0,525420 );
    // autre recopie de valeur

  5. #5
    Membre averti
    Inscrit en
    Décembre 2006
    Messages
    23
    Détails du profil
    Informations forums :
    Inscription : Décembre 2006
    Messages : 23
    Par défaut
    Oups, j'avais pas réalisé que c'était le post délesté.

    Depuis, j'ai reçu une nouvelle version de la dll native et donc j'ai dû modifier quelque peu les structures pour qu'elles correspondent aux nouvelles fonctions dont voici la signature d'initialisation :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    [DllImport(@"FPQC.dll", EntryPoint = "InitImage", SetLastError = true, CharSet = CharSet.Auto)]
    public static extern IntPtr InitImage(IntPtr ptrRaw, UInt32 width, UInt32 height, float resolution, int rank, out IntPtr ptrFpImage);
    Cette fonction retourne une structure de type ErrorContext déclarée comme suit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    [StructLayout(LayoutKind.Sequential)]
    public class ErrorContext
    {
        [MarshalAs(UnmanagedType.I4)]
        public T__FPQC_Returned_Code returnedCode;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)]
        public String errorMessage;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
        public String errorFile;
        [MarshalAs(UnmanagedType.U4)]
        public UInt32 errorLine;
    }
    La fonction prend en input une série de paramètres dont le dernier est de type out IntPtr qui correspond à ce qui suit:
    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
     
    [StructLayout(LayoutKind.Sequential)]
    public class Image
    {
        [MarshalAs(UnmanagedType.ByValArray)]
        public byte[] imgData;
        [MarshalAs(UnmanagedType.U4)]
        public UInt32 imgWidth;
        [MarshalAs(UnmanagedType.U4)]
        public UInt32 imgHeight;
        [MarshalAs(UnmanagedType.R4)]
        public float imgResolution;
        [MarshalAs(UnmanagedType.I1)]
        public sbyte rank;
        [MarshalAs(UnmanagedType.U4)]
        public Int32 initok;
        [MarshalAs(UnmanagedType.I4)]
        public T__FPQC_Struct_Type type;
    }
    Le problème qu'il me reste à résoudre est le passage des paramètres pour que la fonction initialise la structure Image avec l'appel suivant :
    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
     
    byte[] raw = GetBytes(bmp);
    IntPtr ptrRaw = Marshal.AllocHGlobal((Marshal.SizeOf(raw[0])) * raw.Length);
    Marshal.Copy(raw, 0, ptrRaw, raw.Length);
    ErrorContext eContext = new ErrorContext();
    Image img = new Image();
    img.imgData = new byte[raw.Length];
    raw.CopyTo(img.imgData, 0);
    img.rank = (sbyte)rank;
    img.imgHeight = (uint)bmp.Height;
    img.imgWidth = (uint)bmp.Width;
    img.imgResolution = bmp.VerticalResolution;
    img.initok = 123;
    img.type = 111;
    IntPtr ptrImage = Marshal.AllocHGlobal(Marshal.SizeOf(img));
    Marshal.SizeOf(ptrImage));
    IntPtr ptrErr = Marshal.AllocHGlobal(Marshal.SizeOf(eContext));
    ptrErr = InitImage(ptrRaw, (uint)bmp.Width, (uint)bmp.Height, img.imgResolution, img.rank, out ptrImage);
    Marshal.PtrToStructure(ptrErr, eContext);

  6. #6
    Membre éclairé
    Inscrit en
    Juillet 2007
    Messages
    357
    Détails du profil
    Informations forums :
    Inscription : Juillet 2007
    Messages : 357
    Par défaut
    poste la declaration de ta fonction en C maisdans ton cas tu n as pas besoin d utiliser je pense de Intptr , utilise une structure Image a la place de ta classe.

    un petit truc , si tu envoi en param "out" un tableau ou une structure contenant un tableau tu doit declarer le pramaetre dans ta fonction sous la forme

    [In,Out] Image

    Sinon tout se passe bien mais les valeur entre manage et non manage ne sont pas affectée car par default l'interoperatibilité ne le fait pas pour des raisons pas evidentes de performances.

  7. #7
    Membre averti
    Inscrit en
    Décembre 2006
    Messages
    23
    Détails du profil
    Informations forums :
    Inscription : Décembre 2006
    Messages : 23
    Par défaut
    ZashOne

    Voici comme demandé la déclaration de la fonction en C:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Error_Context InitImage(const UInt8 *i__imagedata, UInt32 i__imagewidth, UInt32 i__imageheight, SInt32 i__imageresolution, SInt8 i__rank, Image *o__Image);
    dans ton cas tu n as pas besoin d utiliser je pense de Intptr
    J'ai modifié les paramètres IntPtr pour avoir ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    [DllImport(@"FPQC.dll", EntryPoint = "InitImage", SetLastError = true, CharSet = CharSet.Auto)]
    public static extern IntPtr InitImage(byte[] raw, UInt32 width, UInt32 height, float resolution, int rank, [In, Out] image);
    Lors de l'appel de la fonction Init, je soulève l'exception :
    "Attempted to read or write protected memory. This is often an indication that other memory is corrupt."
    Voici le code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    byte[] raw = GetBytes(bmp);
    Image img = new Image();
    img.imgData = new byte[raw.Length];
    raw.CopyTo(img.imgData, 0);
    img.rank = (sbyte)rank;
    img.imgHeight = (uint)bmp.Height;
    img.imgWidth = (uint)bmp.Width;
    img.imgResolution = bmp.VerticalResolution;
    img.initok = 123;
    img.type = 111;
    IntPtr ptrErr = IntPtr.Zero;
    ptrErr = InitImage(raw, (UInt32)bmp.Width, (UInt32)bmp.Height, bmp.HorizontalResolution, rank, img);
    Mais je ne comprends pas pourquoi
    pour tout ZashOne

  8. #8
    Membre éclairé
    Inscrit en
    Juillet 2007
    Messages
    357
    Détails du profil
    Informations forums :
    Inscription : Juillet 2007
    Messages : 357
    Par défaut
    Image , dans ton api,ca doit etre une structure dont la declaration est fournie avec ton api et pas une classe a mon avis. Poste la egalement.

    de plus dans la declaration de ta fonction , tu as Image *o__Image.

    Donc tu doit envoyer l adresse de ta classe/structure et pas ta Classe/structure. En C#, dans ton dllimport tu doit donc avoir
    et tu appele via

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ptrErr = InitImage(raw, (UInt32)bmp.Width, (UInt32)bmp.Height, bmp.HorizontalResolution, rank, ref img);

  9. #9
    Membre averti
    Inscrit en
    Décembre 2006
    Messages
    23
    Détails du profil
    Informations forums :
    Inscription : Décembre 2006
    Messages : 23
    Par défaut
    Image , dans ton api,ca doit etre une structure dont la declaration est fournie avec ton api
    Tout à fait, c'est une structure dont voici la déclaration:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    typedef struct {
    T__UInt8	*m__imagedata;
    T__UInt32	m__imagewidth;
    T__UInt32	m__imageheight;
    T__UInt32	m__imageresolution;
    T__SInt8	m__rank;
    T__UInt32	m__initok;   
    T__Struct_Type m__structtype;    
    }Struct_Image;
    Je fais un test avec tes remarques et je te tiens au courant

  10. #10
    Membre averti
    Inscrit en
    Décembre 2006
    Messages
    23
    Détails du profil
    Informations forums :
    Inscription : Décembre 2006
    Messages : 23
    Par défaut
    Voilà, tout fonctionne presque parfaitement
    Pas d'erreur à la compilation et pas d'exception non plus
    Seul hic , la fonction InitImage ne renvoie pas le bon code d'erreur. Le message que je reçoit m'indique que les dimensions, longueur et largeur, ne sont pas comprises entre 256 et 4096.
    Or je suis certain que c'est le cas puisque mes images font 512*512.
    J'ai même essayé avec:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ptrErr = InitImage(raw, 512, 512, bmp.HorizontalResolution, rank, ref img);
    à la place de :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ptrErr = InitImage(raw, bmp.Width, bmp.Height, bmp.HorizontalResolution, rank, ref img);
    Evidemment, si le code d'erreur n'est pas success, img n'est pas initialisé.
    Le problème ne vient de la fonction native non plus car elle est utilisée par d'autres programmes et là ça fonctionne.
    Si quelqu'un a une idée, je suis preneur.


  11. #11
    Membre éclairé
    Inscrit en
    Juillet 2007
    Messages
    357
    Détails du profil
    Informations forums :
    Inscription : Juillet 2007
    Messages : 357
    Par défaut
    le typedef du T__UInt32 c quoi , tu es sur que c est pas une adresse qu il cherche?

  12. #12
    Membre averti
    Inscrit en
    Décembre 2006
    Messages
    23
    Détails du profil
    Informations forums :
    Inscription : Décembre 2006
    Messages : 23
    Par défaut
    le typedef du T__UInt32 c quoi
    c'est simplement une redéfinition de int32 dans un fichier .h comme montré ci-dessous :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    #ifdef _WIN32
    typedef unsigned __int32        T__UInt32;
    typedef signed __int32          T__SInt32;
    #else
    typedef unsigned int            T__UInt32;
    typedef signed int              T__SInt32;
    #endif
    tu es sur que c est pas une adresse qu il cherche?
    J'en suis certain.

    Je ne vois malheureusement pas où se situe le problème
    Marshalling ou autre???

    En tout cas ZashOne pour ton aide précieuse

  13. #13
    Membre éclairé
    Inscrit en
    Juillet 2007
    Messages
    357
    Détails du profil
    Informations forums :
    Inscription : Juillet 2007
    Messages : 357
    Par défaut
    si tu envoi 512 pour un int tu recois un int de l autre coté , vu que il y a des margeur-hauteur dans ta struct a mon avis le probleme se passe la , reli bien la doc de ton api.

    Sinon voila ce que tu peux faire ,
    cree une solution contenant une dll C qui prend et renvoi les meme valeur et en interne appel ton api.
    Ensuite cree une appli mfc ou win32 qui appele cette dll pour valider.
    Pour terminer dans ta solution rajoute une appli .net qui appelera ta dll. Dans les propriété de ta solution , tu peux cocher "Allow unmanaged code debug", de la sorte tu verra ce qui se passe un peu mieux.

Discussions similaires

  1. [Forms]Passage de paramètre entre Forms et Reports
    Par jack554 dans le forum Reports
    Réponses: 4
    Dernier message: 30/03/2004, 13h58
  2. probleme lors du passage de paramètre
    Par maxmj dans le forum ASP
    Réponses: 4
    Dernier message: 18/11/2003, 00h15
  3. [XSL] Passage de paramètres à un template
    Par pantin dans le forum XSL/XSLT/XPATH
    Réponses: 2
    Dernier message: 27/06/2003, 13h28
  4. passage de paramètres
    Par pram dans le forum XMLRAD
    Réponses: 5
    Dernier message: 18/02/2003, 17h28
  5. passage en paramètre d'un array dynamique 2D
    Par Guigui_ dans le forum Langage
    Réponses: 4
    Dernier message: 27/11/2002, 19h47

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