Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1450 connectés 

  FORUM HardWare.fr
  Programmation
  C#/.NET managed

  utilisation en C de fonctions écrites en C#

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

utilisation en C de fonctions écrites en C#

n°1714981
jpg16
Posté le 09-04-2008 à 13:56:20  profilanswer
 

bonjour,
 
Mon problème est le suivant : je dispose d'une dll écrite en C# avec le visual studio 2008 (code 'managé' avec net framework 3.5), et je souhaite utiliser les fonctions de cette dll ds un programme C++ standard (non managé).  
 
En guise d'exemple, ma dll ne contient actuellement qu'une seule fct :
 
public class Class1
{
  public static int functopo()
  {
    return 11;
  }
}
 
 
J'ai résolu un 1er problème : rendre les fcts exportées 'visibles' pour le code non managé; en gros cela consiste à générer le fichier .il (intermediate langage) à partir de la dll, y modifier quelques lignes puis regénérer la dll (pour + de détails : http://www.c-sharpcorner.com/Uploa [...] ged.aspx). Après cette manipulation, l'outil Dependency Walker me montre bien les fonctions exportées par la dll.
 
Ensuite je génère un fichier .def :
LIBRARY   DLLTOPO
EXPORTS
   functopo  
 
puis un fichier .lib (confer http://support.microsoft.com/kb/131313/en-us), et ds visual studio 2005 j'incorpore ce lib ds mon projet C++ ; le code appelant la fct de dll :
 
extern int functopo();
 
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR     lpCmdLine, int  nCmdShow)
{
  functopo();
  ...
}
 
--> erreur au linkage : error LNK2001: unresolved external symbol "int __cdecl functopo(void)" (?functopo@@YAHXZ)
 
Je sais que __cdecl est la 'calling convention' propre au C, et que en C# c'est la _stdcall convention qui est utilisée, mais à ce stade je suis bloqué.


Message édité par jpg16 le 11-04-2008 à 09:02:14
mood
Publicité
Posté le 09-04-2008 à 13:56:20  profilanswer
 

n°1715404
Tarabiscot​e
Posté le 10-04-2008 à 08:47:55  profilanswer
 

Tu devrais plutôt mettre :

extern "C" int functopo();


Si tu veux utiliser la même fonction que celle du .def.
Ca devrait déjà linker, tu rajouteras ensuite le _stdcall si tu ne veux pas que ca plante lors de l'exécution.
 
Remarque en supposant que ta dll soit correcte : vu qu'elle n'a pas de paramètre ca devrait marcher sans _stdcall même si ce n'est pas très propre.

n°1716036
jpg16
Posté le 11-04-2008 à 08:38:21  profilanswer
 

j'ai exposé mon problème ds un autre forum (experts-exchange), on m' a conseillé à peu près la même déclaration de fct :
 
extern "C" __declspec(dllimport) int functopo();  
 
çà fonctionne, mais effectivement les problèmes dès qu'on commence à passer des paramètres ; si je passe un int :
extern "C" __declspec(dllimport) int functopo(int x);  
 
l'appel de la fct provoque le msg suivant :
"The value of ESP was not properly saved across a function call. This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention."
Néanmoins le code continue ensuite, et la valeur retournée est bien celle attendue.
 
Je ne vois pas comment rajouter le  _stdcall :
extern stdcall "C" int functopo(int x);  
provoque "error C2059: syntax error : 'string"

n°1716080
Tarabiscot​e
Posté le 11-04-2008 à 10:30:46  profilanswer
 

Et avec un _ devant stdcall ca marche pas non plus ?

n°1716126
jpg16
Posté le 11-04-2008 à 11:07:40  profilanswer
 

erreur de frappe ds mon précédent message, mais en fait ds mon code j'avais bien mis  
extern _stdcall "C" int functopo(int x);

n°1716147
Tarabiscot​e
Posté le 11-04-2008 à 11:37:40  profilanswer
 

Essaye plutôt :

extern "C" _stdcall int functopo(int x);

n°1716157
jpg16
Posté le 11-04-2008 à 11:55:22  profilanswer
 

j'avais essayé çà aussi, c'est pire ... :
 
Compiling...
warning C4518: 'int ' : storage-class or type specifier(s) unexpected here; ignored
warning C4230: anachronism used : modifiers/qualifiers interspersed, qualifier ignored
Linking...
error LNK2001: unresolved external symbol _functopo@4

n°1716220
Tarabiscot​e
Posté le 11-04-2008 à 13:19:45  profilanswer
 

Autant pour moi je crois que c'est :

extern "C" int _stdcall functopo(int x);


 
Et tu dois modifier ton .def en rajoutant @4 après le nom de ta fonction (qui correspond au nombre d'octet en paramètre : int = 4 octets sur ta machine)

n°1716243
jpg16
Posté le 11-04-2008 à 13:51:19  profilanswer
 

comme çà, çà compile et çà linke, mais ne çà s'exécute pas : "le point d'entrée de procédure functopo@4 est introuvable dans la bibliothèque de liaisons dynamique dlltopo.dll"

n°1716344
Tarabiscot​e
Posté le 11-04-2008 à 15:02:41  profilanswer
 

Ok je ne me souvient plus exactement de la syntaxe mais ca doit être entry=function@N donc en gros ton .def devrait ressembler à ca :

LIBRARY   DLLTOPO  
EXPORTS  
   functopo=functopo@4

mood
Publicité
Posté le 11-04-2008 à 15:02:41  profilanswer
 

n°1716360
jpg16
Posté le 11-04-2008 à 15:10:26  profilanswer
 

merci pour ta persévérance ...  
mon .def était en effet différent de ce que tu proposes :
 
LIBRARY   DLLTOPO
EXPORTS
   functopo@4
 
là j'ai fini boulot, je teste çà lundi, encore merci

n°1717079
jpg16
Posté le 14-04-2008 à 08:20:23  profilanswer
 

test avec fichier .def corrigé (functopo=functopo@4) -->
Linking...
calltopo.obj : error LNK2001: unresolved external symbol _functopo@4

n°1717419
Tarabiscot​e
Posté le 14-04-2008 à 18:57:02  profilanswer
 

Essaye ça :

LIBRARY   DLLTOPO  
EXPORTS  
   functopo=_functopo@4


 
Pour faire court :
- à gauche du "=" c'est ce que t'as dans ta dll.
- à droite c'est ce que ton compilateur te demande.
 
Si c'est la même chose pas besoin de "=".


Message édité par Tarabiscote le 14-04-2008 à 18:57:51
n°1717533
jpg16
Posté le 15-04-2008 à 08:46:40  profilanswer
 

--> même résultat : le linker ne connait pas _functopo@4

n°1718052
Tarabiscot​e
Posté le 15-04-2008 à 19:04:31  profilanswer
 

Je disais ça de tête, c'est peut être dans l'autre sens (j'ai pas de quoi tester actuellement) :
 

LIBRARY   DLLTOPO    
EXPORTS    
   functopo@4=functopo


n°1718408
jpg16
Posté le 16-04-2008 à 11:32:22  profilanswer
 

idem (_functopo@4 inconnu) ...

n°1718849
Tarabiscot​e
Posté le 16-04-2008 à 23:01:51  profilanswer
 

Bon j'ai vérifié sur des .def que j'avais et j'ai bien dans le style la :

LIBRARY   DLLTOPO  
EXPORTS  
   functopo@4


Mais je doit dire que j'avais utilisé gcc à l'époque, enfin comme tu disais qu'il n'y avait pas de problème de link, je ne suis pas sûr que le problème viens de là.
 
Sinon tu peux essayer en mettant l'ordinal de la fonction que tu peux voir avec depends (rajouter un espace et @N après le nom de la fonction).
Pour l'ordinal 1 ça donnerait quelque chose comme ça :

LIBRARY   DLLTOPO  
EXPORTS  
   functopo@4 @1


Si ça marche il faudrait voir pour fixer la valeur de l'ordinal quand tu crées la dll.

n°1719169
jpg16
Posté le 17-04-2008 à 12:56:52  profilanswer
 

Je me suis demandé si tu voulais me faire tourner en bourrique ... mais cette fois, en ajoutant l'ordinal de la fct de le .def,  çà passe complètement, j'ai une fonction qui transmet un entier et retourne un entier.  
Maintenant on peut passer aux choses sérieuses ... il faudrait que je passe une string , donc en C un tableau de char. Tu m'as déjà ôté une fameuse épine du pied, mais peut-être pourrai-je encore compter sur ton expérience.
 
Mes 1er essais :
 
En c# je reçois le paramètre en tant que tableau de byte (pas de char, sachant qu'en c# les char sont de l'unicode donc des double bytes); la fct suivante vérifie juste que je peux accèder aux différents char de ma string :
 
public static int functopo(byte[] s)
{
 int c = s[0];
 return c;
}
 
et en c :
extern "C" int _stdcall functopo(char * s);
 
int x = functopo("123456" );
 
Cà passe pour la lecture du 1er char : la fct retourne 49 (code ascii de "1" ).
 
Mais dès que j'essaye d'accéder aux caractères suivants ( int c = s[1] ds la fct c#), j'ai une "unhandled exception in calltopo.exe (KERNEL32.DLL: 0xE0434F4D: (no name)".
 
 

n°1719274
jpg16
Posté le 17-04-2008 à 16:07:14  profilanswer
 

bon quand j'ai trouvé un gourou je deviens paresseux ...
après un peu de recherche , je vois que je peux très bien utiliser des pointeurs en c# (code unsafe) -->
 
unsafe public static int functopo(byte* s)
et plus de problème pour accèder à tous les chars de ma string

n°1719310
jpg16
Posté le 17-04-2008 à 17:00:19  profilanswer
 

et pour conclure voici la manière de convertir le byte * en string du c# :
string str1 = System.Runtime.InteropServices.Marshal.PtrToStringAnsi(new IntPtr((int)s));


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C#/.NET managed

  utilisation en C de fonctions écrites en C#

 

Sujets relatifs
utilisation de nombre entier tres grand!Pointeurs de fonctions et polymorphisme
Utilisation d'un driver[AJAX] utilisation de listbox générées
utilisation de NOT en VBAutilisation d'une procedure stockée TSQL depuis access
[UML]Extends : mon diagramme de cas d'utilisation est bon?Utilisation de cellpadding
Collection a double dimension avec utilisation de la généricitéUtilisation d'un case of
Plus de sujets relatifs à : utilisation en C de fonctions écrites en C#


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR