Utilisation dll C/C++ en C# [Résolu]

garcimor59 66 Messages postés mardi 18 juillet 2006Date d'inscription 6 mars 2008 Dernière intervention - 22 sept. 2006 à 10:09 - Dernière réponse : Lutinore 3248 Messages postés lundi 25 avril 2005Date d'inscription 27 octobre 2012 Dernière intervention
- 28 sept. 2006 à 18:13
Bonjour tout le monde,

Bon voilà j'ai mon probleme :

J'ai une DLL faite en C/C++, et j'aimerais pouvoir faire appelle à des fonctions contenus dans cette DLL dans mon application C#. Mais comme je veux y faire reference Visual Studio 2003 me dit que ne s'agit pas d'une assembly valide......

Donc j'ai essayé de créer une bibliotheque de classe (.NET) C++ qui fait appelle à la DLL C/C++
pour ensuite utilisé cette bibliotheque dans mon application C#, pour cela j'ai inclus le.H que j'ai.

Mais le probleme c'est qu'il me fait une error LNK2001 symbol externe non reconnu....
J'ai essayé d'ajouter la DLL pareil il fait une erreur (mais pas la meme que celle cité en haut) là il me dit juste qu'il peut pas.

Bon pour m'aider un peu je vous donne plus d'info.

La dll je l'ai testé en C elle fonctionne bien. et j'ai aussi un  .h et un .lib.

Voila merci beaucoup.

++
Afficher la suite 

Votre réponse

18 réponses

Meilleure réponse
cs_Bidou 5507 Messages postés dimanche 4 août 2002Date d'inscription 20 juin 2013 Dernière intervention - 22 sept. 2006 à 10:46
3
Merci
Hello,
Allez, je donne aussi un petit lien pratique (discussion sur le forum)

<hr size="2" />VC# forever

Merci cs_Bidou 3

Avec quelques mots c'est encore mieux Ajouter un commentaire

Codes Sources a aidé 92 internautes ce mois-ci

Commenter la réponse de cs_Bidou
Meilleure réponse
Lutinore 3248 Messages postés lundi 25 avril 2005Date d'inscription 27 octobre 2012 Dernière intervention - 26 sept. 2006 à 04:07
3
Merci
Salut, LPSECURITY_ATTRIBUTES est un pointeur sur une structure, tu dois réécrire la structure avec l'attribut StructLayout ( voir la doc sur PInvoke ) dans ton code en C# en respectant sa définition que tu peux trouver dans la MSDN ou dans le fichier Winbase.h du SDK Windows. Mais comme c'est un pointeur sur une structure il faudra la passer avec le mot clé ref ( là aussi voir la doc PInvoke ). Ou bien tu simules un pointeur NULL avec IntPtr.Zero. ( passer un uint comme dans l'exemple que tu as trouvé n'est pas la meilleure façon de faire ).

Les constantes sont définies dans les fichiers headers ( *.h ) du C/C++ que tu trouves dans le SDK Windows ou dans Visual Studio.

http://www.pinvoke.net/default.aspx/kernel32/CreateFile.html

Merci Lutinore 3

Avec quelques mots c'est encore mieux Ajouter un commentaire

Codes Sources a aidé 92 internautes ce mois-ci

Commenter la réponse de Lutinore
Meilleure réponse
Lutinore 3248 Messages postés lundi 25 avril 2005Date d'inscription 27 octobre 2012 Dernière intervention - 28 sept. 2006 à 18:13
3
Merci
C'est quoi emission + 1 ? emission + 1 byte ou emission + sizeof( MESSAGE_EMI ) ?

Il y a quelque chose qui ne colle pas dans ta structure, 'option', 'reserve', 'taille' sont de type long en C ils devraient être des int en C#.

Merci Lutinore 3

Avec quelques mots c'est encore mieux Ajouter un commentaire

Codes Sources a aidé 92 internautes ce mois-ci

Commenter la réponse de Lutinore
MorpionMx 3489 Messages postés lundi 16 octobre 2000Date d'inscription 30 octobre 2008 Dernière intervention - 22 sept. 2006 à 10:17
0
Merci
Salut,

pour utiliser une dll en c/c++ non managé, en C#, il faut regarder du coté du p/invoke.
Je te laisse aller lire ce post

Au fait, on ne peut pas voir tes images, car elles sont en local, sur ton poste

Mx
MVP C# 
Commenter la réponse de MorpionMx
garcimor59 66 Messages postés mardi 18 juillet 2006Date d'inscription 6 mars 2008 Dernière intervention - 22 sept. 2006 à 11:01
0
Merci
Oki merci beaucoup, je regarde ça.

Quelles images?
Commenter la réponse de garcimor59
MorpionMx 3489 Messages postés lundi 16 octobre 2000Date d'inscription 30 octobre 2008 Dernière intervention - 22 sept. 2006 à 11:03
0
Merci
Il y a 4 images qui ne s'affichent pas en dessous de ton "++". "moz-screenshot.jpg" , ...





Mx
MVP C#
 
Commenter la réponse de MorpionMx
garcimor59 66 Messages postés mardi 18 juillet 2006Date d'inscription 6 mars 2008 Dernière intervention - 22 sept. 2006 à 11:36
0
Merci
Lol bizarre moi je vois rien...
Commenter la réponse de garcimor59
cs_Bidou 5507 Messages postés dimanche 4 août 2002Date d'inscription 20 juin 2013 Dernière intervention - 22 sept. 2006 à 11:45
0
Merci
Chez toi les images s'affichent car elles sont sur ton disque, mais nous on les voit pas...

[file:///C:/DOCUME~1/assystem/LOCALS~1/Temp/moz-screenshot-3.jpg file:///C:/DOCUME~1/assystem/LOCALS~1/Temp/moz-screenshot-3.jpg]
[file:///C:/DOCUME~1/assystem/LOCALS~1/Temp/moz-screenshot.jpg file:///C:/DOCUME~1/assystem/LOCALS~1/Temp/moz-screenshot.jpg]

par exemple...
C'est ta signature qui n'est pas au point je pense !

<hr size="2" />VC# forever
Commenter la réponse de cs_Bidou
garcimor59 66 Messages postés mardi 18 juillet 2006Date d'inscription 6 mars 2008 Dernière intervention - 22 sept. 2006 à 12:42
0
Merci
Lol mais je vois pas d'image chez moi, et j'ai pas voulu mettre d'image non plus!!

Mort de rire c'est quoi ce bug!!

bon sinon pour revenir à nos moutons : j'ai essayé la méthode indiquée dans les liens que vous m'avez donnés. Mais il me fait une erreur que je ne comprends pas : "Identificateur attendu, char est un mot clé :

[DllImport("toto.dll", CharSet=CharSet.Auto)]
public static extern long Emission (char* szNomPipeEmi, unsigned char* cBuffer)

Merci
Commenter la réponse de garcimor59
garcimor59 66 Messages postés mardi 18 juillet 2006Date d'inscription 6 mars 2008 Dernière intervention - 22 sept. 2006 à 16:17
0
Merci
Re, bon pour les char etc... il faut utiliser le tableau de conversion de cette page :

http://www.microsoft.com/france/msdn/vcsharp/Utilisez-Pinvoke.mspx#docum_topic3

Et la page est tres bien en elle-meme pour inserer dll C/C++ en C#
Commenter la réponse de garcimor59
Lutinore 3248 Messages postés lundi 25 avril 2005Date d'inscription 27 octobre 2012 Dernière intervention - 23 sept. 2006 à 00:53
0
Merci
Salut,

"char*" c'est le type en C comme tu l'as compris il faut le convertir vers C#. Dans ton cas c'est String ou StringBuilder si le type est en entrée/sortie et l'attribut CharSet.Ansi.

( Tu pourrais utiliser directement le pointeur char même en C# )

Le tableau de conversion des types :



http://msdn.microsoft.com/library/fre/default.asp?url=/library/FRE/cpguide/html/cpconplatforminvokedatatypes.asp
Commenter la réponse de Lutinore
garcimor59 66 Messages postés mardi 18 juillet 2006Date d'inscription 6 mars 2008 Dernière intervention - 25 sept. 2006 à 11:58
0
Merci
Bonjour tout le monde,

Alors voilà, je souhaite utilisé la fonction C++ CreateFile :
The [ lpFileName]</italique>,
DWORD[ dwDesiredAccess],
DWORD[ dwShareMode],
LPSECURITY_ATTRIBUTES[ lpSecurityAttributes],
DWORD[ dwCreationDisposition],
DWORD[ dwFlagsAndAttributes],
HANDLE[ hTemplateFile]
);

Donc pour cela j'utilise la méthode qu'on a vu plus haut avec le DLLIMPORT avec une
conversion de type grace au lien :
http://msdn.microsoft.com/library/fre/default.asp?url=/library/FRE/cpguide/html/cpconplatforminvokedatatypes.asp

Donc mon premiere probleme, c'est que LPSECURITY_ATTRIBUTES je ne sais pas en quoi le convertir.

Ensuite lors de l'appel de cette fonction à l'origine j'ai :

CreateFile(slotname, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

Et bien sur il ne connait pas GENERIC_WRITE et autres...

Alors comment puis-je faire pour qu'il accepte ces constantes.

Merci beaucoup.
Commenter la réponse de garcimor59
garcimor59 66 Messages postés mardi 18 juillet 2006Date d'inscription 6 mars 2008 Dernière intervention - 25 sept. 2006 à 12:06
0
Merci
Un lien interressant qui repond à la premiere partie de ma question :

http://msdn2.microsoft.com/fr-fr/library/2d9wy99d.aspx

Par contre je sais pas comment je peux avoir les valoirs des constantes, autrement dit comment puis-je savoir que :

const uint GENERIC_READ = 0x80000000;

Merci
Commenter la réponse de garcimor59
garcimor59 66 Messages postés mardi 18 juillet 2006Date d'inscription 6 mars 2008 Dernière intervention - 26 sept. 2006 à 10:54
0
Merci
Excellent lien merci beaucoup.
Commenter la réponse de garcimor59
garcimor59 66 Messages postés mardi 18 juillet 2006Date d'inscription 6 mars 2008 Dernière intervention - 26 sept. 2006 à 15:00
0
Merci
Bonjour,

J'ai encore quelques petits problemes.
Donc voilà j'utilise des fonctions contenus dans kernel32.dll. Donc grace à votre aide et DLLImport j'ai réussi à les implementés dans mon code C#.

J'utilise notamment la fonction WriteFile :




//Code C
// hfile : handle, m : structure MESSAGE_EMI
WriteFile(hfile, m, sizeof(MESSAGE_EMI), &NbWritten, NULL);

ma structure MESSAGE_EMI en C:
typedef struct //Buffer d'envoi compatible IPT
{
    char nomLiaison[15];
    char filler1;
    char nomMes[16];   
    long option;      
    float dvie;
    long reserve;
    long taille;
    char data[32000]; 
}MESSAGE_EMI;

Donc en C# j'ai donc :

[System.Runtime.InteropServices.DllImport("kernel32", SetLastError = true)]
static extern unsafe bool WriteFile
   (
       IntPtr hFile,
       string lpBuffer,
       int nNumberOfBytesToWrite,
       out uint lpNumberOfBytesWritten,
       int lpOverlapped
   );

lpBuffer est de type char * dans mon application C.
Donc en utilisant le tableau de conversion(lien que l'on ma donné) j'ai utilisé un string à la place.

De plus autre probleme, ma structure MESSAGE_EMI je la recrée en C# donc je n'utilise pas Struct_Layout
et j'ai mis des string pour remplacer les tableaux de caracteres.  (C'est peut-etre pas top).

J'ai également essayé avec un lpBuffer en char [], mais sans résultat non plus.

Autre chose à savoir, j'utilise WriteFile pour écrire dans une mailbox, et si je n'envoi pas la structure
MESSAGE_EMI comme defini plus haut le programme (independant) chargé d'envoyer les messages de la mailbox vers
les autres pc ne se declenche pas.

Merci par avance.

N'hésitez pas à me dire si je n'ai pas été clair.
Commenter la réponse de garcimor59
garcimor59 66 Messages postés mardi 18 juillet 2006Date d'inscription 6 mars 2008 Dernière intervention - 26 sept. 2006 à 16:37
0
Merci
Re bonjour,

Bon j'ai des nouveaux éléments qui pourront peut-etre vous aider à m'aider (lol).

Aprés avoir fait environ un million de test à peu prés (lol), je pense qu'il faut que je passe en parametre de WriteFile
une chaine avec de  0 à 14 le nom de ma liaison en 15eme position filler1 etc...

Mais bon avec les string j'ai jamais la bonne taille puisque le nom de ma liaison ne fait pas forcement 15 caracteres.
Donc j'ai declaré nomLiaison et nomMessage et data comme des char []
Et dans mon constructeur je leur affecte une taille (ex : nomLiaison = new char [15])
Jusqu'ici tout va bien.

Mais lorsque j'essaie d'affecter une chaine à mes char[] je passe par un string et la fonction ToCharArray()

Mais en faisant des tests avant et aprés l'affectation je me rends compte qu'avant l'affectation nomLiaison fait bien 15,
mais aprés elle est plus petite (normal je met que 11 caractere dedans) cependant j'aimerais que l'espace alloué à nomLiaison
soit toujours de 15, ainsi lorsque je passe ma structure en parametre j'ai bien telle chose à telle position ....

Pour information, vu que dans ma fonction WriteFile lpBuffer est un char (ou un string) je concatene tout les éléments de ma structure
MESSAGE_EMI pour lui passé en tant que char[] (ou string).
Personne aurait une solution plus simple pour que je puisse passé tout les éléments de ma structure sans faire cette manip longue et
fastidieuse?? J'ai essayé avec un ToString mon élément MESSAGE_EMI instancié mais il m'affiche un truc qui a rien à voir.

Enfin voilà un grand merci dejà à ceux qui ont pris la peine de tout lire (lol) et un autre grand merci à ceux qui pourront m'aider.

Cordialement,

G
Commenter la réponse de garcimor59
Lutinore 3248 Messages postés lundi 25 avril 2005Date d'inscription 27 octobre 2012 Dernière intervention - 27 sept. 2006 à 08:28
0
Merci
La fonction WriteFile attend un tableau de bytes. Il est possible d'allouer de l'espace dans la mémore non managée et de passer un IntPtr à la place d'un pointeur void. ou de fixer un tableau en mémoire et de passer un pointeur.




Pour passer un tableau char de taille fixe dans une structure :


[ MarshalAs( UnmanagedType.ByValTStr, SizeConst = 32 ) ]
public String str;


regardes ici :



http://www.csharpfr.com/infomsg_Sous%20avec%20des%20DLLImport_747879.aspx?p=3
Commenter la réponse de Lutinore
garcimor59 66 Messages postés mardi 18 juillet 2006Date d'inscription 6 mars 2008 Dernière intervention - 28 sept. 2006 à 17:24
0
Merci
Bonjour,

Pour m'aider à debugger pourriez-vous m'indiquer une méthode pour connaitre ce qui se trouve à l'emplacement i de ma structure.

Je m'explique plus clairement :

J'ai la structure suivante  :

[ StructLayout( LayoutKind.Sequential, CharSet=CharSet.Ansi)]
        public unsafe struct MESSAGE_EMI
        {
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 15)]
            public string nomLiaison;            //Nom liaison id fichier IPSecure
            public char filler1;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
            public string nomMessage;            //Nom du message
            public short option;                //Option de stockage
            public Single dvie;
            public short reserve;
            public short taille;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32000)]
            public string data;
        }

Lors de mon appel à WriteFile je passe en parametre " ref emission" (avec emission de type MESSAGE_EMI bien sur)

donc en gros j'aimerais savoir ce que j'ai à emission+1.

A c'était mieux au bon vieux temps du C.

Merci
Commenter la réponse de garcimor59

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.