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 :

Reflexion et Cast


Sujet :

C#

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Février 2004
    Messages
    89
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2004
    Messages : 89
    Points : 44
    Points
    44
    Par défaut Reflexion et Cast
    Bonjour,

    Je récupère un pointeur pointeurManaged sur un structure non managée (déclarée et initialisée dans une dll) via une méthode Get_Adresse exportée.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    //   Code du C#
    Init(0);
     
    IntPtr pointeurManaged = (IntPtr)Get_Adresse(0);
    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
     
    //   Code de la DLL
    typedef struct _DLL_TEST_STRUCT
    {
    	unsigned char	Attribut_Bool1;
    	unsigned char	Attribut_Bool2;
    	short			Attribut_Short1;
    	int				Attribut_Int1;
    	double			Attribut_Double1;
    }	DLL_TEST_STRUCT;
     
    int* Get_Adresse(int notused)
    {
    	return (int*) Test_Struct;
    }
     
    void Init(int notusded)
    {
    	Test_Struct = calloc(1, sizeof(DLL_TEST_STRUCT));
     
    	Test_Struct->Attribut_Bool1 = 1;
    	Test_Struct->Attribut_Bool2 = 1;
    	Test_Struct->Attribut_Short1 = 1;
    	Test_Struct->Attribut_Int1 = 1;
    	Test_Struct->Attribut_Double1 = 1;
    }
    je caste ensuite ce "pointeurManaged" de 2 façons différentes :


    Méthode 1 :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    DLL_TEST_STRUCT* pointeurManagedStructure = (DLL_TEST_STRUCT*)pointeurManaged;
    ET

    Méthode 2 :
    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, Pack = 4)]
    public unsafe struct CS_TEST_STRUCT
    {
        public bool Attribut_Bool1;
        public bool Attribut_Bool2;
        public short Attribut_Short1;
        public Int32 Attribut_Int1;
        public double Attribut_Double1;
    }
     
    object objectManaged = *(CS_TEST_STRUCT*)pointeurManaged;
    Si je modifie la structure via le pointeur de la méthode 1, je modifie bien en mémoire la structure :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    pointeurManagedStructure->Attribut_Bool1 = false;
    pointeurManagedStructure->Attribut_Bool2 = false;
    pointeurManagedStructure->Attribut_Short1 = 10; 
    pointeurManagedStructure->Attribut_Int1 = 1000;
    pointeurManagedStructure->Attribut_Double1 = 10000;
    Par contre, j'ai beau modifié mon objet "objectManaged ", je ne modifie pas en mémoire la structure non managée.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    Type _type = objectManaged.GetType();
    FieldInfo[] fields = _type.GetFields();
    for (int j = 0; j < fields.Length; j++)
    {
       if (fields[j].FieldType.ToString() == "System.Int32")
       {
          fields[j].SetValue(objectManaged, 0);
       }
    }
    Pourquoi ? Est ce possible ?

    Merci de votre aide.

    Pascal

  2. #2
    Membre confirmé
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    547
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 547
    Points : 627
    Points
    627
    Par défaut
    Salut,

    oui, c'est normal, car la procedure emise par le compilateur C# est differente. Dans le premier cas, tu as juste un cast qui va caster ta structure en void*, ce pointeur pointant toujours vers la memoire non managé. Dans le deuxieme cas, un castant vers un type object, tu créés une copie de la valeur de la memoire non managé vers un type managé (le fonctionnement normal des types valeurs pour la CLR).

    Bref, si tu veux modifier la memoire non managé, il faut rester en unsafe et jouer du pointeur (gloups !). Alternativement, tu peux aussi faire tes chagements, et repercuter apres tes changements (en gardant le pointeur, et en faisant un Marshal.StructToPointer par la suite).

    Bon courage.

  3. #3
    Expert confirmé
    Avatar de ced600
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Août 2006
    Messages
    3 364
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Août 2006
    Messages : 3 364
    Points : 4 061
    Points
    4 061
    Par défaut
    Hum si tu cast en objet managé, il déplace la valeur dans une zone mémoire managé car c'est le seul moyen qu'à le framework pour ne serait ce que mettre à disposition du GC cette valeur lorsqu'elle ne sera plus utilisé ?

    Du coup lorsque l'on fait du code non managé, l'idéal serait de faire une classe qui a pour rôle d'être une interface, une classe adapteur.
    Elle gérerais le passage des valeur entre le code managé et le non managé.
    Elle récupérerais les pointeur et les conservrais en private, et grace à des property, elle copierais la valeur dans un zone mémoire managé pour le get, et ferais le Marshal.StructToPointer pour le set.

    Cette solution de classe interface memoire managé/non managé te simplifierais la vie je pense.
    Dans le reste du code cela serait assez transparent.
    Pourquoi faire compliqué lorsque l'on peut faire encore plus compliqué.

  4. #4
    Membre du Club
    Profil pro
    Inscrit en
    Février 2004
    Messages
    89
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2004
    Messages : 89
    Points : 44
    Points
    44
    Par défaut Merci
    Je me doutais qu'il y'avait une copie la dessous...

    Je vais creuser cela...

    Merci.

    Pascal

  5. #5
    Expert confirmé
    Avatar de ced600
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Août 2006
    Messages
    3 364
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Août 2006
    Messages : 3 364
    Points : 4 061
    Points
    4 061
    Par défaut
    La je faisais une réflexion niveau conception, car je ne connais pas la syntaxe non managé, donc l'exemple que je vais te donner ne compile pas forcement :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public class IntManNoMan()
    {
          private pointeurManaged pt1;
          public pointeurManaged  Pt1
          {
               get {//Le code avec objectManaged pour récupérer le pointeur et le mettre dans une case mémoire managé.}
               set {//Le code pour copié ce que vaut ton pointeur dans la case mémoire non managé.}
          }
          ......
    }
    Bref c'est suivre l'idée de SirJulio, mais de mettre tout cela dans une classe avec des properties pour faciliter ensuite son utilisation.
    Pourquoi faire compliqué lorsque l'on peut faire encore plus compliqué.

Discussions similaires

  1. Reflexion et Cast dynamique
    Par Gurdil le nain dans le forum VB.NET
    Réponses: 7
    Dernier message: 21/04/2011, 18h08
  2. [Reflexion?] Casting dynamique
    Par diaboloche dans le forum Windows Forms
    Réponses: 2
    Dernier message: 03/11/2008, 13h57
  3. CAST DATETIME ----> SMALLDATETIME
    Par Guizz dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 26/06/2003, 12h07
  4. traduction en delphi "reinterpreted cast"
    Par Chupakabra dans le forum Langage
    Réponses: 3
    Dernier message: 13/02/2003, 15h49

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