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 :

Passer Double[][][][][][] de C# a C++


Sujet :

C#

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2011
    Messages
    25
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2011
    Messages : 25
    Par défaut Passer Double[][][][][][] de C# a C++
    Bonjour
    Donc voici mon problème je travaille actuellement sur un programme C# utilisant une dll C++. La dll aurait besoin d'un double[][][][][][] afin de fonctionner mais je ne sais pas comment lui faire passer, j'ai essayer avec un marshaller personnalisé mais je n'ai pas réussi a le faire fonctionner: cf le code ci dessous ou d'aplatir le tableau en un double[] mais cette solution est trop lourde pour le programme. Avez vous des solutions?
    Merci d'avance
    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
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    public class JaggedArrayMarshaler : ICustomMarshaler
        {
            static ICustomMarshaler GetInstance(string cookie)
            {
                return new JaggedArrayMarshaler();
            }
            GCHandle[] handles;
            GCHandle[] handles2;
            GCHandle[] handles3;
            GCHandle[] handles4;
            GCHandle[] handles5;
            GCHandle buffer;
            Array[] array;
            Array[] array2;
            Array[] array3;
            Array[] array4;
            Array[] array5;
            public void CleanUpManagedData(object ManagedObj)
            {
            }
            public void CleanUpNativeData(IntPtr pNativeData)
            {
                buffer.Free();
                foreach (GCHandle handle in handles)
                {
                    handle.Free();
                }
                foreach (GCHandle handle in handles2)
                {
                    handle.Free();
                }
                foreach (GCHandle handle in handles3)
                {
                    handle.Free();
                }
                foreach (GCHandle handle in handles4)
                {
                    handle.Free();
                }
                foreach (GCHandle handle in handles5)
                {
                    handle.Free();
                }
            }
            public int GetNativeDataSize()
            {
                return IntPtr.Size;
            }
     
            public IntPtr MarshalManagedToNative(object ManagedObj)
            {
                array = (Array[])ManagedObj;
     
                handles = new GCHandle[array.Length];
                for (int i = 0; i < array.Length; i++)
                {
                    array2 = (Array[])array[i];
                    handles2 = new GCHandle[array2.Length];
                    for (int j = 0; j < array2.Length; j++)
                    {
                        array3 = (Array[])array2[j];
                        handles3 = new GCHandle[array3.Length];
                        for (int k = 0; k < array3.Length; k++)
                        {
                            array4 = (Array[])array3[k];
                            handles4 = new GCHandle[array4.Length];
                            for (int l = 0; l < array4.Length; l++)
                            {
                                array5 = (Array[])array4[l];
                                handles5 = new GCHandle[array5.Length];
                                for (int m = 0; m < array5.Length; m++)
                                {
                                    handles5[m] = GCHandle.Alloc(array5[m], GCHandleType.Pinned);
     
                                }
                                IntPtr[] pointers5 = new IntPtr[handles5.Length];
                                for (int m = 0; m < handles5.Length; m++)
                                {
                                    pointers5[m] = handles5[m].AddrOfPinnedObject();
                                }
                                handles4[l] = GCHandle.Alloc(pointers5, GCHandleType.Pinned);
                            }
                            IntPtr[] pointers4 = new IntPtr[handles4.Length];
                            for (int l = 0; l < handles4.Length; l++)
                            {
                                pointers4[l] = handles4[l].AddrOfPinnedObject();
                            }
                            handles3[k] = GCHandle.Alloc(pointers4, GCHandleType.Pinned);
                        }
                        IntPtr[] pointers3 = new IntPtr[handles3.Length];
                        for (int k = 0; k < handles3.Length; k++)
                        {
                            pointers3[k] = handles3[k].AddrOfPinnedObject();
                        }
                        handles2[j] = GCHandle.Alloc(pointers3, GCHandleType.Pinned);
                    }
                    IntPtr[] pointers2 = new IntPtr[handles2.Length];
                    for (int j = 0; j < handles2.Length; j++)
                    {
                        pointers2[j] = handles2[j].AddrOfPinnedObject();
                    }
                    handles[i] = GCHandle.Alloc(pointers2, GCHandleType.Pinned);
                }
                IntPtr[] pointers = new IntPtr[handles.Length];
                for (int i = 0; i < handles.Length; i++)
                {
                    pointers[i] = handles[i].AddrOfPinnedObject();
                }
                buffer = GCHandle.Alloc(pointers, GCHandleType.Pinned);
                return buffer.AddrOfPinnedObject();
            }
            public object MarshalNativeToManaged(IntPtr pNativeData)
            {
                return array;
            }
        }

  2. #2
    Membre Expert

    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2010
    Messages
    2 067
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Novembre 2010
    Messages : 2 067
    Par défaut
    Bonjour,
    je crois que ce que tu cherches est les tableaux multidimensionnels en c# http://msdn.microsoft.com/fr-fr/library/2yd9wwz4.aspx après je suis pas un connaisseur en c++ mais je pense que c'est ça.

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2011
    Messages
    25
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2011
    Messages : 25
    Par défaut
    Non malheureusement, cette variable double[][][][][][] existe déjà dans le programme que je modifie, je ne peux donc pas le modifier en tableaux multi-dimensions, réecrire cette variable dans un double[,,,,,] reviendrait à la même chose que de l'aplatir en une dimension. c'est pour ça que j'essaie de le faire passer comme sa en renvoyant un IntPtr grace au Marshaller.

  4. #4
    Membre Expert Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Par défaut
    Bonjour.

    Je n'ai pas pris le temps de le tester mais ça doit fonctionner. Note que la liste de handles peut, elle, être aplatie. En revanche les tableaux de IntPtr sont correctement imbriqués.

    Code c# : 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
    IntPtr Marshal(Array sourceArray)
    {
        if (sourceArray is double[]) return Pin(sourceArray);
     
        int targetIndex = 0;
        var targetArray = new IntPtr[sourceArray.Length];
     
        foreach (Array sourceChild in sourceArray)
        {
            targetArray[targetIndex++] = Marshal(sourceChild);
        }
     
        return Pin(targetArray);
    }
     
    IntPtr Pin(Array array)
    {
        var handle = GCHandle.Alloc(array, GCHandleType.Pinned);
        Handles.Add(handle);
        return handle.AddrOfPinnedObject();
    }
     
    readonly List<GCHandle> Handles = new List<GCHandle>();

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2011
    Messages
    25
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2011
    Messages : 25
    Par défaut
    Merci de ta réponse mais ne connaissant pas tellement les Intptr , je ne sais pas si c'est pas moi qui ne sais pas utilisé correctement ce code ou si il ne marche pas. Etant donné que je passe un tableau de double [][][][][][], suis-je censé prévoir en entrée de la dll un pointeur double* ou un pointeur de pointeur...
    Passé le intPtr que la fonction IntPtr Marshal(Array sourceArray) a la fonction de ma dll est il correct (elle prend pour l'instant un double*) ?

  6. #6
    Membre Expert Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Par défaut
    Je recommande d'utiliser IntPtr. IntPtr représente n'importe quel pointeur et peut toujours être substitué à ces derniers dans les signatures d'importation (du moins pour les paramètres d'entrée). A vrai dire je déconseille d'importer des fonctions en déclarant des pointeurs, à moins de vouloir expressément utiliser ces fonctions dans des blocs de code unsafe (dans ce cas la bonne signature serait double******).

    Cela dit on peut très facilement passer d'un pointeur à un IntPtr via les opérateurs de conversion puisque ceux-ci désignent la même chose. IntPtr n'est qu'une facilité donnée pour faire circuler des adresses dans du code managé

    Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    double* ptr = (double*)(void*)IntPtr.Zero;
    IntPtr intPtr = (IntPtr)(void*)ptr;

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Passer un Double en paramètre dans un setText()
    Par jesuislibre15 dans le forum Débuter avec Java
    Réponses: 1
    Dernier message: 13/04/2012, 23h12
  2. Réponses: 1
    Dernier message: 25/01/2009, 01h10
  3. Réponses: 17
    Dernier message: 26/02/2007, 17h45
  4. Passer de DOUBLE PRECISION en NUMERIC
    Par alex4 dans le forum SQL
    Réponses: 5
    Dernier message: 18/10/2004, 16h24
  5. Passer en mode 800*600
    Par flavien tetart dans le forum Assembleur
    Réponses: 8
    Dernier message: 30/05/2002, 23h05

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