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 :

PInvoke. Passer struct contenant pointeur vers autres struct de C# à C.


Sujet :

C#

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2009
    Messages
    145
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Espagne

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2009
    Messages : 145
    Par défaut PInvoke. Passer struct contenant pointeur vers autres struct de C# à C.
    Voici mon problème. J'ai ce code en C:
    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
     
    GTO_EXPORT(int )  GtoCapFloorAvgVol(
        TDate capStartDate,                  /* (I)  */
        TDate capExpiryDate,                 /* (I) */
        double *strikeRates,                 /* (I) */
        int numStrikeRates,                  /* (I) */
        double *principles,                  /* (I) */
        int numPrinciples,                   /* (I) */
        int moneymarketDen,                  /* (I) # days/year */
        TDateInterval *resetPeriod,          /* (I) Time Between caplets */
        int optionType,                      /* (I) Cap or Floor */
        char stubPosition,                   /* (I) 2/16/94 GG 'F'ront or 'B'ack */
        TCurve *zeroCurve,                   /* (I) For discounting */
        double price,                        /* (I) Price */
        double avgVolGuess,                  /* (I) Average Volatility guess */
        double *avgVol);                      /* (O) Average Volatility */
     
    Et voici les structs:
    typedef struct _TCurve
    {
        int       fNumItems;     /* Number of TRatePts in fArray */
        TRatePt  *fArray;        /* Dates & rates */
        TDate     fBaseDate;     /* Discount date */ 
        double    fBasis;        /* Number compounding periods / year */
        long      fDayCountConv; /* How the year fraction is computed */
        void     *fClassHandle;  /* C++ class handle implementation */ 
    } TCurve;
     
    typedef struct
    {
        TDate  fDate;
        double fRate;
    } TRatePt;
     
    et j'ai typedef long int TDate;
    J'écris un wrapper en C#. Voici ce que j'ai:
    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
     
            [DllImport("alib.dll", EntryPoint = "GtoCapFloorAvgVol")]
            public static extern int CapFloorAvgVol(
                long capStartDate,                  /* (I)  */
                long capExpiryDate,                 /* (I) */
                double[] strikeRates,                /* (I) */
                int numStrikeRates,                  /* (I) */
                double[] principles,                 /* (I) */
                int numPrinciples,                   /* (I) */
                int moneymarketDen,                  /* (I) # days/year */
                ref TDateInterval resetPeriod,       /* (I) Time Between caplets */
                int optionType,                      /* (I) Cap or Floor */
                char stubPosition,                   /* (I) 2/16/94 GG 'F'ront or 'B'ack */
                [In] IntPtr zeroCurve,                /* (I) For discounting Pointer to TCurve*/
                double price,                        /* (I) Price */
                double avgVolGuess,                  /* (I) Average Volatility guess */
                out double avgVol);                  /* (O) Average Volatility */
     
    [StructLayout(LayoutKind.Sequential)]
        public struct TRatePt
        {
            public long fDate;
            public double fRate;
        };
     
        public struct TCurve
        {
            public int fNumItems;             /* Number of TRatePts in fArray */
            public TRatePt[] fArray;          /* Dates & rates */
            public long fBaseDate;            /* Discount date */
            public double fBasis;         //ZERO_CURVE_BASIS in capvoll.c which is #defined as ANNUAL_BASIS 1   /* Number compounding periods / year */
            public long fDayCountConv;   //ZERO_CURVE_DAY_COUNT_CONV in capvoll.c which is #defined as GTO_ACT_365F; = 2L /* How the year fraction is computed */
            public IntPtr     fClassHandle;  /* C++ class handle implementation */
        };
    Pour l'appel de la fonction je fais ça:
    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
     
    //create zeroCurve with data above and then does the necessary for it to be a pointer as required by C++ dll
                TCurve _zeroCurve = new TCurve()
                                {
                                    fBaseDate = _tempValueDate,
                                    fNumItems = _tempZeroCurveDates.Length,
                                    fArray = _ratePoints,
                                    fBasis = 2L,
                                    fDayCountConv = 1
                                };
                int _sizeOfTCurve = Marshal.SizeOf(typeof(TCurve));
                IntPtr p_zeroCurve = Marshal.AllocHGlobal(_sizeOfTCurve);
                Marshal.StructureToPtr(_zeroCurve, p_zeroCurve, false);
     
                int _status =  CapFloorAvgVol(_tempStartDate, _temPexpiryDate, strikeRates, strikeRates.Length, principles, principles.Length, moneymarketDen,
                                                    ref _resetPeriod, optionType, stubPosition, p_zeroCurve, price, avgVolGuess, out avgVol);
    En gros je déclare un pointeur et le passe à la fonction. Maintenant, j'ai un problème au niveaus du fArray... Côté C il ne contient pas du tout les bonnes valeures. Du coup j'ai du me tromper quelque part? Peut-être que je dois rajouter un MarshalAs dans TCurve mais je vois pas quoi?

    Est-ce que je l'ai bien défini? Dois-je aussi le définir en tant que pointeur dans TCurve? Je l'ai pas fait parce que je pense les membres sont blittable donc devrait pouvoir être passé directement non?

    PS: dsl pour les quelques mots d'anglais, je ne connais pas le vocabulaire en français...

    Merci d'avance au courageux qui voudraient bien m'aider.

  2. #2
    Membre éprouvé
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    135
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 135
    Par défaut
    C'est toi qui est courageux de te faire mal comme ça !

    Es-tu obligé de faire ça via des p/invoke sur du C natif ?

    Ne peux tu pas compiler ton code en C++ managé (option /clr) et créer une fonction qui prend des arguments managés (ex : System::String^ , si tu n'as jamais touché au C++ managé) ?

    C'est plus simple d'utiliser des données managées en C++ plutot que d'exporter des données managées vers le C en C# !

  3. #3
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2009
    Messages
    145
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Espagne

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2009
    Messages : 145
    Par défaut compilé en c++ managé
    en faisant ça est-ce que j'aurais pas le même problème? Il faudra bien que je redéfinissent mes structs en C# ou C++ et puis rebelote pour les fonctions qui prennent des arguments managé non?

    si non, comment inclure /clr pour la compilation dans VS 2005?

  4. #4
    Membre éprouvé
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    135
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 135
    Par défaut
    Mouais, après réflexion, c'est un conseil empoisonné que je te donne.

    Ce genre d'approche te permet de référencer ton assembly C++ en tant qu'assembly .NET depuis ton projet C# et de définir au sein de ton assembly C++ (et toujours en C++, mais managé ce coup ci) des classes et méthodes appelables sans p/invoke depuis ton code C#

    Ca te permet de passer des objets .Net complexes à ton code C++, depuis lequel tu pourrais extraire les informations que tu juges utiles pour les utiliser dans du code managé.

    Mais ça ne règle pas vraiment ton problème de mapping...
    C'est juste une autre approche, et je ne sais pas si c'est celle qu'il te faut : Ca dépend de ce que tu fais avec ta classe qui pointe vers une structure derrière !


    Quant à VS 2005 ... je ne sais pas ... je suis sous VS 2010

  5. #5
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2009
    Messages
    145
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Espagne

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2009
    Messages : 145
    Par défaut
    D'accord. Et sinon pour le problème du "marshallage" t'as une idée? La dernière version de mon code est là:
    http://stackoverflow.com/questions/7...-to-c-p-invoke

  6. #6
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2009
    Messages
    62
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2009
    Messages : 62
    Par défaut
    Une chose, je ne comprend pas pourquoi tu ne garde pas la même structure en C#, tu peux très bien garder tes pointeurs C++ dans ta structure C# en la declarant unsafe.

    Exemple tout bête

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    public unsafe struct Toto
    {
            char* Tata;
    }
    Car j'ai un doute quand au cast pointeur C++ -> tableau [] .net

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

Discussions similaires

  1. Passage d'une struct contenant un tableau d'une DLL vers C#
    Par morgan_2956 dans le forum C++/CLI
    Réponses: 2
    Dernier message: 03/02/2010, 09h11
  2. Pointeur vers struct
    Par guiyomh dans le forum Débuter
    Réponses: 6
    Dernier message: 09/10/2008, 14h36
  3. Réponses: 15
    Dernier message: 12/09/2007, 11h19
  4. Réponses: 4
    Dernier message: 27/10/2006, 17h03
  5. copie d'une struct avec pointeur
    Par Thor Tillas dans le forum C++
    Réponses: 5
    Dernier message: 18/10/2006, 02h41

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