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 :

Question: Comment consommer une DLL C++ 2005 en C# ?


Sujet :

C#

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre habitué
    Inscrit en
    Octobre 2009
    Messages
    8
    Détails du profil
    Informations forums :
    Inscription : Octobre 2009
    Messages : 8
    Par défaut Question: Comment consommer une DLL C++ 2005 en C# ?
    Bonjour à tous,

    Tout d'abord j'espère ne pas me tromper d'endroit, y a du C#, du C++ et du VB donc entre les trois mon topic balance.


    Voici mon soucis, je conçois actuellement une appli en .NET 4.5 C# et je dois consommer une dll d'un fournisseur qui a été produite en Visual C++ 2005.
    Hors la doc de la dll explique juste comment consommer celle-ci en VB ou C++, pas en .NET !

    J'ai beau consulter les forums et faire mes propres expériences rien n'y fait, soit j'ai un retour null soit des nombres aléatoires (pointeur je suppose).

    Voici l'appel d’après la doc en VB:

    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
    Declare Function StartJob Lib "calcdll.dll" (ByRef p1 As Double, ByRef p2 As Variant, ByRef
    p3 as Double) As Boolean
     
    Const NINPUTDATA = 100
    Const NRESDATA = 100
    Const NOPTIONSDATA = 1
    Const P60 = 1
     
    Dim aInputData(NINPUTDATA) As Double
    Dim aResult(NRESDATA) As Variant
    Dim aOptions(NOPTIONSDATA) As Variant
     
    aInputData(0) = 1 
    aInputData(1) = 32
    aInputData(2) = 50
    aInputData(5) = 2000
    ...
     
    a = StartJob(aInputData(0), aResult(0), aOptions(0))
    La définition de la méthode C++ :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    extern "C" BOOL FAR PASCAL EXPORT StartJob(double vInp[NINPUTDATA], VARIANT vRis[NRESDATA], double
    vOpt[NOPTIONSDATA]);
    Et quelques infos utiles (ou pas):
    DLLs are written with Visual C++ 2005, and the user needs to distribute the VC++ runtime also.
    The DLL is compiled as UNICODE.
    J'ai donc tenté de faire de même en C# mais je désespère en voyant les résultats que j'obtiens.
    Voici mon code:

    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
     [DllImport(DllPath, EntryPoint = "StartJob", CharSet = CharSet.Unicode)]
        private static extern bool StartJob( double[] p1, object[] p2, object[] p3);
     
          private const int NINPUTDATA = 100;
          private const int NRESDATA = 100;
          private const int NOPTIONSDATA = 1;
     
          private static double[] aInputData = new double[NINPUTDATA];
          private static object[] aResult = new object[NRESDATA];
          private static object[] aOptions = new object[NOPTIONSDATA];
     
     
        private static void Main(string[] args)
        {
          aInputData[0] = 94;
          aInputData[1] = 60;
          aInputData[2] = 10.4;
          aInputData[5] = 5200;
          //...
     
          var result = StartJob(aInputData, aResult, aOptions);
    Et là, ben paf ça fait des chocapics !
    Je ne sais quoi mettre à la place des objects... Qu'est-ce qu'un VARIANT ? Est-ce vraiment un array ? Dois-je faire du marshalling horrible que je ne comprends pas ?

    Mon aResult qui est un array pouvant contenir des nombres, textes, etc... me revient avec 100 entrées 'null'.
    Si je remplace par IntPtr ou byte, j'ai des nombres totalement aléatoires (adresse pointeur, donc au moins il se passe quelque chose).

    Pourriez-vous m'aider afin que j'obtienne ce que j'attends de cette maudite DLL ?

    En vous remerciant d'avance.

    Phil

  2. #2
    Membre éclairé Avatar de stolx_10
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2006
    Messages
    374
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 374
    Par défaut
    Bonjour

    essayez ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    private static extern bool StartJob( ref double[] p1, ref object[] p2, ref object[] p3);
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    var result = StartJob(ref aInputData[0], ref aResult[0], ref aOptions[0]);

  3. #3
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    27 131
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 27 131
    Billets dans le blog
    150
    Par défaut
    (Ceci est la réponse de Philippe.S, que je poste, suite à un soucis technique)
    ---

    Voici la solution pour ce cas après avoir perdu la moitié de mes cheveux :

    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
     
    [DllImport(DllDirectory + DllName, EntryPoint = "StartJob")]
    private static extern bool StartJob(double[] inputs, ref OutputStructure outputs, double[] options); 
    // L'objet de type OutputStructure remplace dans ce cas si le type VARIANT non défini dans du code managé.
     
     private const int NINPUTDATA = 100;
     private const int NOPTIONSDATA = 1;
     
    // Contrôle la disposition d'un objet lorsqu'il est exporté dans du code non managé. (Source: MSDN)
     [StructLayout(LayoutKind.Explicit)]
        private struct OutputStructure
        {
          [FieldOffset(8)] // Dans ce cas ci je commence par l'offset 8 car il semblerai que les 8 premiers bits soit déjà occupé.
          private readonly double _monDouble1;
     
          [FieldOffset(24)] // Avancement par pas de 16 bits
          private readonly double _monDouble2;
     
          [FieldOffset(40)]
          private readonly double _monDouble3;
     
          [FieldOffset(56)
          private readonly IntPtr _monString1; //Les string retournent une adresse de pointeur
     
          [FieldOffset(72)]
          private readonly double _monDouble4;
          //...
     
          public double  MonDouble1 { get { return _monDouble1; } }
          public double MonDouble2 { get { return _monDouble2; } }
          public double  MonDouble3 { get { return _monDouble3; } }
          public string MonString1{ get { return  Marshal.PtrToStringAuto(_monString1); } } // Le fameux marshalling pour récupérer les caractères du string.
          // Marshal : Fournit une collection de méthodes pour l'allocation de mémoire non managée, la copie de blocs de mémoire non managée et la conversion de types managés en types non       managés, ainsi que diverses autres méthodes utilisées lors de l'interaction avec du code non managé. (Source: MSDN)
          // PtrToStringAuto : Alloue un objet String managé et copie tous les caractères - jusqu'au premier caractère null - d'une chaîne stockée dans de la mémoire non managée dans cet objet. (Source: MSDN)
          public double MonDouble4 { get { return _monDouble4; } }
          //...
        }
     
          var inputs = new double[NINPUTDATA];
          var options = new double[NOPTIONSDATA];
          var outputs = new OutputStructure();
     
          for (var i = inputs.GetLowerBound(0); i < inputs.GetUpperBound(0); i++)
               inputs[i] = 0;
          for (var i = options.GetLowerBound(0); i < options.GetUpperBound(0); i++)
               options[i] = 0;
     
          inputs[0] = data1;
          inputs[1] = data2;
          inputs[2] = data3;
          //...
     
          var result = StartJob(inputs, ref outputs, options);
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

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

Discussions similaires

  1. Réponses: 4
    Dernier message: 02/10/2005, 13h01
  2. Comment accéder à une DLL COM depuis un exécutable ?
    Par Denys dans le forum API, COM et SDKs
    Réponses: 10
    Dernier message: 20/09/2005, 08h04
  3. Comment exécuter une DLL ?
    Par chleuh dans le forum Langage
    Réponses: 4
    Dernier message: 29/06/2005, 14h27
  4. Comment créer une dll Win32 sous Delphi ?
    Par Mickey.jet dans le forum Langage
    Réponses: 8
    Dernier message: 16/06/2005, 15h38

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