[VB.NET] Utiliser une DLL C++
Bonjour à tous.
J'ai à utiliser dans mon application vb.net 2010 des fonctions contenues dans une dll en C++.
Voici le code de ma dll :
.cpp
Code:
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
| #include "stdafx.h"
#include <stdlib.h>
#include <stdio.h>
#include "MARRE.h"
namespace MARRE {
int __clrcall MARRE::compareDoubles (const void *Y, const void *Z)
{
double y = *((double *)Y);
double z = *((double *)Z);
if (y > z)
{
return 1;
}
else
{
if (y < z)
{
return -1;
}
else
{
return 0;
}
}
}
} |
.h
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| #pragma once
#include "windows.h"
#include <iostream>
using namespace std;
using namespace System;
namespace MARRE {
public ref class MARRE
{
// TODO: ajoutez ici vos méthodes pour cette classe.
public :
int __clrcall compareDoubles (const void *Y, const void *Z);
};
} |
Lors de la compilation de la dll, tout se passe bien (à noter que j'ai essayé également d'utiliser __declspec (dllexport), de déplacer le public, d'enlever le ref etc).
J'enregistre alors dans mon projet vb.net cette dll. Le namespace apparait bien, la classe également, mais aucune fonction n'est disponible... on dirait qu'il ne connait pas ma fonction CompareDoubles...
http://img213.imageshack.us/i/dllu.jpg/
J'ai utilisé comme logiciel "Dll Export Viewer", qui reconnait alors ma fonction et me la déclare publique ET exportée...
Suis-je obligée d'utiliser DllImport ou Déclare ? Je ne peux pas utiliser mon namespace comme n'importe quel autre namespace ? (la dll contiendra un bon nombre de fonctions :cry:)
Quelqu'un s'y connaissant en vb.net et c pourrait m'indiquer quelle option j'ai du oublier ?
type c++ void, reference en vb.net,nothing
bonjour leeloo
Cela ne marche pas a cause du type "void" pour les const ,car il n' y a d'equivalent en vb.net pour le "void" d'une constante(constante sans type),ni pour des types references pour les doubles,integer et boolean.
voici le code avec des variables "types" doubles qui marche :
Code:
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
| // DLLMarre.h
// il ne faut avoir marre comme mr jeanmarre(bande dessine belge des annees 60)
#pragma once
using namespace System;
namespace DLLMarre {
public ref class MARRE
{
// TODO*: ajoutez ici vos méthodes pour cette classe.
public :
// void => sans type n'est pas pris en charge
int __clrcall compareDoubles (const void *Y, const void *Z);
// type reference sur double =>n'est pas pris en charge
int __clrcall compareDoublesBis(const double *Y, const double *Z);
// type explicite double pris en charge
int __clrcall compareDoublesTris(const double Y, const double Z);
};
}
// Il s'agit du fichier.cpp DLL principal.
#include "stdafx.h"
#include "DLLMarre.h"
namespace DLLMarre {
int __clrcall MARRE::compareDoubles(const void *Y, const void *Z)
{
double y = *((double *)Y);
double z = *((double *)Z);
if (y > z)
{
return 1;
}
else
{
if (y < z)
{
return -1;
}
else
{
return 0;
}
}
}
int __clrcall MARRE::compareDoublesBis(const double *Y, const double *Z)
{
double y = *((double *)Y);
double z = *((double *)Z);
if (y > z)
{
return 1;
}
else
{
if (y < z)
{
return -1;
}
else
{
return 0;
}
}
}
int __clrcall MARRE::compareDoublesTris(const double Y, const double Z)
{
double y = ((double )Y);
double z = ((double )Z);
if (y > z)
{
return 1;
}
else
{
if (y < z)
{
return -1;
}
else
{
return 0;
}
}
}
} |
Code:
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
| 'Projet VB.Net
'simple fichier Forme
Imports System
Imports System.Windows
Imports DLLMarre
Public Class Form1
Dim objMARRE As MARRE = New MARRE
Public Sub New()
' Cet appel est requis par le Concepteur Windows Form.
InitializeComponent()
' Ajoutez une initialisation quelconque après l'appel InitializeComponent().
End Sub
'compilateur vb.net "gueule"(warn) ->type de parametres non pris en
'charge.
'effectivement il n'y a d'equivalent en vb.net pour:
'-"sans type" (void)
'- de type reference pour une constante .
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
'ceci n'est pas visible
'Dim nn1 As Integer = objMARRE.compareDoubles(10.0, 10.0)
'ceci n'est pas visible
''Dim nn2 As Integer = objMARRE.compareDoublesBis(10.0, 10.0)
'ceci est visible car le type est explicite
Dim nn3 As Integer = objMARRE.compareDoublesTris(10.0, 10.0)
Me.TextBox1.Text = nn3.ToString
End Sub
End Class |
petit conseil: quand on fait de la programmation inter-language tous les problemes viennent du marshalling des types.C'est la qu'il faut veiller au grain.
Ce type existe-t-il dans l'autre language ou quel est l'equivalent?voila la question sempiternelle.
bon code.........
liste vb.net dans c++/cli
bonjour leeloo64
oui bien sur dans C++/CLI (pour le c++natif cela peut impliquer un travail enorme) tu passer des listes avec des valeurs et des dates.
Cette possibilite peut etre tres facile si ce sont tes propres DLL comme elle peut devenir tres limite ou ardue pour des dll d'api tierce .
si ce sont les tiennes ou bien tu as acces au code source C++/CLI voici un exemple de classe CLI sous traitante avec une liste:
code c++:
Code:
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 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193
| // projet Library C++/Cli
// generique pour d'autres languages NET.cpp
// compile with: /clr
//
// GenericPourVBNet.h
#pragma once
using namespace System;
using namespace System::Collections::Generic;
using namespace System::Globalization;
using namespace System::Runtime::InteropServices;
namespace GenericPourVBNet {
//
//Objet Exporte
//
public ref class ExportVBNET {
// champs prives:
private :
String ^ m_Chaine;
int m_Entier;
double m_Reel ;
String ^ m_DateString ;
DateTime m_Date ;
bool m_Test;
public :
//proprietes
property String ^ CHAINE
{
String^ get(){return m_Chaine;}
void set(String^ value) {m_Chaine = value;}
}
property double REEL
{
double get(){return m_Reel;}
void set(double value) {m_Reel = value;}
}
property int ENTIER
{
int get(){return m_Entier;}
void set(int value) {m_Entier = value;}
}
property String ^ DATESTRING
{
String^ get(){return m_DateString;}
void set(String^ value) {m_DateString = value;}
}
property DateTime DATE
{
DateTime get(){return m_Date;}
void set(DateTime value) {m_Date = value;}
}
property bool TEST
{
bool get(){return m_Test;}
void set(bool value) {m_Test = value;}
}
// TODO*: ajoutez ici vos méthodes pour cette classe.
// Ctor
__clrcall ExportVBNET::ExportVBNET(void);
//autres methodes
void __clrcall ExportVBNET::Method1(String^ str);
void __clrcall ExportVBNET::Method2(int nbEntier,double nbReel);
DateTime __clrcall ExportVBNET::Method3(DateTime objDate1,DateTime objDate2) ;
ExportVBNET^ __clrcall ExportVBNET::Method4(ExportVBNET^ obj);
};
//
//Classe Auxiliaire pour exporter une liste(publique)
//
public ref class GereListe
{
private:
List<ExportVBNET^>^ m_nouvListe ;
public:
//Constructeur
GereListe::GereListe (void)
{
m_nouvListe = gcnew List<ExportVBNET^>;
}
property List<ExportVBNET^>^ NouvListeCLI
{
List<ExportVBNET^>^ get(){return m_nouvListe;}
void set(List<ExportVBNET^>^ value) {m_nouvListe = value;}
}
//Methode globale renvoie une liste cree en CLI
List<ExportVBNET^>^ __clrcall renvoiListeCLI();
//Methode globale renvoie une liste cree en CLI
List<ExportVBNET^>^ __clrcall modifieListeCLI(List<ExportVBNET^>^ objListe);
};
}
// projet Library C++/Cli
// Il s'agit du fichier DLL principal.
// GenericPourVBNet.cpp
#include "stdafx.h"
#include "GenericPourVBNet.h"
#include <iostream>
using namespace std;
using namespace System;
using namespace System::Collections::Generic;
using namespace System::Globalization;
namespace GenericPourVBNet
{
//Methode Constructeur(New)
//
ExportVBNET::ExportVBNET(void){
m_Chaine = "Item vb.net";
m_Entier = 200;
m_Reel = 500.5;
m_DateString="10/02/2011";
m_Date=DateTime::Now;
m_Test = true;
}
//Methode1:recoit une chaine
//La modifie et Renvoi à VB.NET
//
void __clrcall ExportVBNET::Method1(String^ str)
{
str="bonjour vb.net";
CHAINE=str;
};
//Methode2:recoit 2 nbres (entier,reel).
//Les multiplies et Renvoi à un nbre Double à VB.NET
//
void __clrcall ExportVBNET::Method2(int nbEntier,double nbReel)
{
nbReel=250.5;
nbEntier=3;
nbReel=nbEntier*nbReel;
ENTIER=3;
REEL=nbReel;
};
//Methode3:recoit 2 Dates
//renvoie la plus grande
//
DateTime __clrcall ExportVBNET::Method3(DateTime objDate1,DateTime objDate2)
{
//modifie objDate1 & objDate2
if( objDate1 < objDate2 )
{
return objDate2;
}
else
{
return objDate1;
}
};
//Methode4:lit date au Format chaine FR dans prop DATESTRING
//Renvoi la date à VB.NET au format US dans prop DATE
//au format Format US.Utilise DateTimeOffset
ExportVBNET^ __clrcall ExportVBNET::Method4(ExportVBNET^ obj)
{
//Change culture
String^ symbRegLng ="en-US";
CultureInfo^ maCulture =gcnew CultureInfo(symbRegLng);
DateTimeFormatInfo^ fmt= gcnew DateTimeFormatInfo;
fmt = maCulture->DateTimeFormat;
//Mets dans prop Date
obj->DATE=(DateTime)DateTime::Parse(obj->DATESTRING, fmt);;
//renvoie obj
return obj;
};
//Methode renvoiListeCLI :
//Remplit une Liste et la Renvoi à VB.Net
//
List<ExportVBNET^>^ __clrcall GereListe::renvoiListeCLI()
{
GereListe^ objGereListe = gcnew GereListe ;
for (int i=0; i< 9;i++)
{
ExportVBNET^ objExportVBNET = gcnew ExportVBNET;
NouvListeCLI->Add(objExportVBNET);
};
return NouvListeCLI ;
};
List<ExportVBNET^>^ __clrcall GereListe::modifieListeCLI(List<ExportVBNET^>^ objListe)
{
for each( ExportVBNET^ elem in objListe)
{
elem->CHAINE = "Item CLI";
elem->ENTIER = 500;
elem->REEL = 257.5;
elem->DATESTRING="10/02/2015";
elem->DATE=DateTime::Now;
elem->TEST = true;
};
return objListe ;
};
} |
code vb.net simple qui l'utilise:
Code:
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 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
| '1er FORM
'-lit une liste initialise dans CLI et l'affiche
'-teste des fonctions sur des entiers,double,et dates
'OBJET EXPORTE PAR CLI : "ExportVBNET"
Imports System
Imports System.Windows
Imports System.Globalization
Imports GenericPourVBNet
Public Class frmConsomGenericCLI
'Liste de l'Objet exporte PAR CLI
Private lstObjExport As List(Of ExportVBNET)
'Classe Generateur de liste
Private objGereCLI As GereListe
'chaine
Dim str As String
Public Sub New()
' Cet appel est requis par le Concepteur Windows Form.
InitializeComponent()
' Ajoutez une initialisation quelconque après l'appel InitializeComponent().
Me.Text = Me.Name
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCreeListeCLI.Click
'Init "gener. liste CLI"
objGereCLI = New GereListe
'Cree une liste "dans CLI" de 10 objets
'La recupere et l'affiche
lstObjExport = objGereCLI.renvoiListeCLI()
txtListeInitiale.Text = ""
For Each elem As ExportVBNET In lstObjExport
txtListeInitiale.Text = txtListeInitiale.Text & vbCrLf
txtListeInitiale.Text = txtListeInitiale.Text & elem.CHAINE.ToString & vbCrLf
txtListeInitiale.Text = txtListeInitiale.Text & elem.DATESTRING & vbCrLf
txtListeInitiale.Text = txtListeInitiale.Text & elem.DATE & vbCrLf
txtListeInitiale.Text = txtListeInitiale.Text & elem.ENTIER.ToString & vbCrLf
txtListeInitiale.Text = txtListeInitiale.Text & elem.REEL.ToString & vbCrLf
txtListeInitiale.Text = txtListeInitiale.Text & elem.TEST.ToString & vbCrLf
Next
'Invoke les methodes de l'objet "ExportVBNET"
Dim objExport As ExportVBNET = New ExportVBNET
Call objExport.Method1("VB.Net")
Me.txtMethodes.Text = objExport.CHAINE
Call objExport.Method2(2, 125.5)
Me.txtMethodes.Text = Me.txtMethodes.Text & objExport.ENTIER.ToString & vbCrLf
Me.txtMethodes.Text = Me.txtMethodes.Text & objExport.REEL.ToString & vbCrLf
'Compare 2 dates chaines et renvoi la plus grande
Dim dt1 As Date = Date.Parse("10/02/2011")
Dim dt2 As Date = Date.Parse("22/02/2011")
dt1 = objExport.Method3(dt1, dt2)
Me.txtMethodes.Text = Me.txtMethodes.Text & dt1.ToString & vbCrLf
'Transmet une date chaine formay "en-US" et recoit une datetime format "fr-FR"
objExport.DATESTRING = "02/10/2011"
objExport = objExport.Method4(objExport)
Me.txtMethodes.Text = Me.txtMethodes.Text & objExport.DATE.ToString & vbCrLf
End Sub
End Class
'2eme FORM
'-initialise la liste en VB.NT
'-la modifie en CLI et affiche resultat
'OBJET EXPORTE PAR CLI : "ExportVBNET"
Imports System
Imports System.Windows
Imports System.Globalization
Imports GenericPourVBNet
Public Class frmUtiliseGenericCLI
'Objet exporte par CLI
Private ObjExport As ExportVBNET
'Liste de l'Objet exporte PAR CLI
Private lstObjExport As List(Of ExportVBNET)
'Classe Generateur de liste
Private objGereCLI As GereListe
Public Sub New()
' Cet appel est requis par le Concepteur Windows Form.
InitializeComponent()
' Ajoutez une initialisation quelconque après l'appel InitializeComponent().
Me.Text = Me.Name
End Sub
Private Sub btnEnvoieListeCLI_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnEnvoieListeCLI.Click
'Init "createur liste CLI"
objGereCLI = New GereListe
lstObjExport = objGereCLI.nouvListeCLI
'Instancie liste 10 objets "dans VB.NET"
'& Affiche Liste
txtListeInitiale.Text = ""
For I As Integer = 0 To 9
ObjExport = New ExportVBNET
ObjExport.CHAINE = "Vient de VB.NET"
ObjExport.ENTIER = 350
ObjExport.REEL = 235.8
ObjExport.TEST = False
ObjExport.DATE = Date.MinValue
ObjExport.DATESTRING = "10/01/2011"
lstObjExport.Add(ObjExport)
txtListeInitiale.Text = txtListeInitiale.Text & ObjExport.CHAINE & vbCrLf
txtListeInitiale.Text = txtListeInitiale.Text & ObjExport.ENTIER.ToString & vbCrLf
txtListeInitiale.Text = txtListeInitiale.Text & ObjExport.REEL.ToString & vbCrLf
txtListeInitiale.Text = txtListeInitiale.Text & ObjExport.TEST.ToString & vbCrLf
txtListeInitiale.Text = txtListeInitiale.Text & ObjExport.DATE.ToString & vbCrLf
txtListeInitiale.Text = txtListeInitiale.Text & ObjExport.DATESTRING & vbCrLf
Next
txtListeInitiale.Text = txtListeInitiale.Text & "nb elem VBNET " & lstObjExport.Count & vbCrLf
End Sub
Private Sub btnRecuperListeCLI_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnRecuperListeCLI.Click
'Fait Modifier la Liste Cree dans VBNET par CLI
lstObjExport = objGereCLI.modifieListeCLI(lstObjExport)
'Reaffiche Liste Modifie par CLI
txtListeModifie.Text = ""
For Each elem As ExportVBNET In lstObjExport
txtListeModifie.Text = txtListeModifie.Text & elem.CHAINE & vbCrLf
txtListeModifie.Text = txtListeModifie.Text & elem.ENTIER.ToString & vbCrLf
txtListeModifie.Text = txtListeModifie.Text & elem.REEL.ToString & vbCrLf
txtListeModifie.Text = txtListeModifie.Text & elem.TEST.ToString & vbCrLf
txtListeModifie.Text = txtListeModifie.Text & elem.DATE.ToString & vbCrLf
txtListeModifie.Text = txtListeModifie.Text & elem.DATESTRING & vbCrLf
Next
txtListeModifie.Text = txtListeModifie.Text & "nb elem CLI " & lstObjExport.Count & vbCrLf
End Sub
End Class |
bon code..........