vanisheur
Messages postés9Date d'inscriptionvendredi 18 juillet 2003StatutMembreDernière intervention11 août 2009
-
9 juin 2009 à 12:12
ssgg
Messages postés1Date d'inscriptionlundi 4 décembre 2000StatutMembreDernière intervention25 novembre 2010
-
25 nov. 2010 à 15:15
Bonjour,
J'ai vraiment besoin d'aide.
je suis en train d'ecrire un programme en C#, celui-ci utilise des fonctions C++ incluses dans des DLL.
Une partie de mon programme fonctionne correctement mais je suis bloqué sur un point particulier :
La declaration des prototypes des fonctions C++ ne posent pas de probleme, le passage ou la recuperation des parametres fonctionne partiellement.
Le soucis vient du fait que certaines fonctions C++ de la DLL demandent :
Un pointeur vers un tableau de structures
la dll est censé y inscrire des informations mais je n'arrive pas a le faire.
Avant de demander votre aide j'ai parcouru tous les ouvrages que je possede sur le sujet, j'ai cherché sur le nt et sur ce forum mais les techniques proposées ne fonctionnent pas, voici mon code plus en detail :
/*public unsafe fixed char device_code[50];
public unsafe fixed char family_code[20];*/
public
unsafe
string device_code;
public
unsafe
string family_code;
}
Appel de la fonction c++ de la dll
_IPL_DEVICE_LIST[] dev_list2 =
new
_IPL_DEVICE_LIST[290];
succeed = IPL_GetDeviceList(
out dev_list2,
1,
ptr_no_devices
);
voici ce qui est censé se passer dans cette fonction :
le premier argument est censé etre un pointeur vers un tableau de strucures,
le second est le Nombre d'elements que l'on demande a la fonction de chercher, un int.
le troisieme est le Nombre d'élements qu'elle a effectivement trouvé, un pointeur d'int.
Lorsque j'appelle cette fonction avec 0 en tant que second parametre, je ne demande PAS a la fonction
d'effectuerer le remplissage du tableau (premier argument), dans ce cas tout fonctionne bien et la fonction me retourne 280 dans le troisieme parametre.
Les choses se gatent si je met par exemple 1 comme ici dans le second parametre, la fonction comprend qu'elle doit me remplir 1 element dans le tableau de structure, autrement dit elle doit ecrire dans la premiere structure du tableau dev_list2.
La j'obtient une exception
Il y a plein d'autres fonctions dans cette dll qui fonctionne sans probleme et auquelles je passe des pointeurs simples de variables primaires comme des int mais la comme je me trouve dans un type reference je n'arrive pas a le faire.
s'il vous plait aidez moi, !!!!
vanisheur
Messages postés9Date d'inscriptionvendredi 18 juillet 2003StatutMembreDernière intervention11 août 2009 9 juin 2009 à 13:51
J'ai commis une legere erreur ci-dessus,
les dll sont ecrites en C, parcontre il y a une programme de demo qui les utilisent et c'est lui qui est ecrit en C++,
Concretement, voici comment ils utilisent la dll dans le code de demo:
Lutinore
Messages postés3246Date d'inscriptionlundi 25 avril 2005StatutMembreDernière intervention27 octobre 201241 9 juin 2009 à 16:50
Salut, tes définitions P/Invoke ne sont pas bien claire, par exemple IPL_GetDeviceList je ne vois pas de type ( ni même de parentheses de fin ) .. Pour la structure IPL_DEVICE_LIST je vois que tu as mis en commentaires les tableaux de caractères, mais faut voir si la définition en C prend des chaines inlines ( ansi ou unicode ) ou des pointeurs char car ça change totalement la taille des structures.
Le C# garantit que les structs d'un tableau sont alignées en mémoire donc il est possible de passer le tableau ou un pointeur fixe sur le tableau à du code C/C++.
vanisheur
Messages postés9Date d'inscriptionvendredi 18 juillet 2003StatutMembreDernière intervention11 août 2009 9 juin 2009 à 19:49
SAlut, merci pour ta reponse.
bon voila ou j'en suis :
je commence a penser que mon probleme se situe au niveau de la structure meme.
celle-ci d'aprés le fournisseur de la dll est tres simple, elle doit comporter 2 tableaux de char dont la taille est precisée :
20 pour le premier et 50 pour le second.
en C# j'ai tenté deux approches, en collant au maximum au tableau de char et en m'adaptant a ce nouveau langage en remplaçant les tableeux de char par des strings.
mais la non plus je n'y arrive pas.
concretement ce qu'il me faut pour me debloquer c'est :
1- reussir a declarer correctement une structure toute simple contenant 2 strings.
2-utiliser cette structure comme modele pour créer un tableau dont chaque element EST cette structure.
3-passer une reference de ce tableau a ma dll.
la dll en question est chargée de piloter en bas niveau (drivers) une sorte de programmateur usb pour microcontroleurs,
j'ai bien avancé car ace stade je communique deja avec l'appareil et il me repond , toujours au travers de pointeurs.
le reste du boulot se fait presque exclusivement en passant et en recuperant ce genre de reference vers un tableau de structures contenant des chaines.
SI quelqu'un parvient a me debloquer , le reste suivra.
S'il vous plait, regardez de plus pret mes 3 etapes et aidez moi a passer a cette dll ce qu'elle me reclame
merci
fab
Vous n’avez pas trouvé la réponse que vous recherchez ?
vanisheur
Messages postés9Date d'inscriptionvendredi 18 juillet 2003StatutMembreDernière intervention11 août 2009 10 juin 2009 à 10:25
Salut Mike,
je ne te connais pas mais je n'ai pas assez de qualificatif pour te remercier, aprés 1 semaine de galere intense tu m'a vraiment bien depanné et meme formé.
Tu l'a compris, ton code marche a la perfection alors je t'adresse donc ce bout de code :
vanisheur
Messages postés9Date d'inscriptionvendredi 18 juillet 2003StatutMembreDernière intervention11 août 2009 10 juin 2009 à 14:28
Je sais c'est encore moi, j'aurai encore besoin de tes lumieres.
j'ai une des fonctions de la dll qui avant ton aide me renvoyer une exception d'acces violation, maintenant elle tourne mais elle me renvoi FALSE sans arret :
cette fonction est censée initialiser l'ouverture du programmateur : on lui passe le numero de serie de l'appareil accompagné d'un ID, la fonction se charge de faire l'init puis nous dis c'est bon.
le N° de serie est 74406, c'est une autre fonction qui me l'a dit et en plus ça correspond bien a l'etiquette sur l'appareil.
L'ID c'est un numero generique que JE choisis qui servira d'alias pour dire , la je m'adresse a l'apareil N° 1 si bien sur mon id vaut 1.
la aussi il faut passer un pointeur vers un tableau de structures (maintenant je sais faire !!!!)
Donc la structure en langage C de la dll demande ceci :
unsigned int SN;
int ID;
j'ai fais ceci :
[StructLayout(
LayoutKind.Sequential)]
public
unsafe
struct
_IPL_INST_CONFIG
{
public
fixed
byte
S_N[4];
public
fixed
byte
ID[2];}
ensuite, la fonction de la dll demande comme arguments ceci:
IPL_INST_CONFIG *config
int n_items
j'ai fais ceci :
[
DllImport
(
"IPL-One.dll"
)][
return
:
MarshalAs
(
UnmanagedType
.Bool)]
private
static
extern
unsafe
bool
IPL_SetInstrumentsConfiguration(
_IPL_INST_CONFIG
* all_configs,
UInt16
n_items );
enfin vient le bout de code qui me renvoie FALSE sans arret mais sans exceptions :
unsafe{
UInt16 itms = 1;
_IPL_INST_CONFIG[] all_configs =
new
_IPL_INST_CONFIG[1];
pour les chiffres en fait j'ai decouper BInairement 74406 en 4 octets, je pense que l'ordre est correct, pods fort et faible pour que la dll qui le recupere comprenne bien 74406, j'ai tout de meme essayé dans les deux sens mais je n'ai droit qu'a du false.
Mike, peut tu me sortir une bouée une fois de plus ??
Lutinore
Messages postés3246Date d'inscriptionlundi 25 avril 2005StatutMembreDernière intervention27 octobre 201241 10 juin 2009 à 15:06
Pourquoi dans la définition de IPL_SetInstrumentConfiguration
utilises tu un UInt16 ? Sur une machine 32 bits ça doit être un int ( Int32 ) comme dans l autre fonction..
[ StructLayout( LayoutKind.Sequential ) ]
public unsafe struct _IPL_INST_CONFIG
{
public fixed byte S_N[ 4 ];
public fixed byte ID[ 2 ];
}
C'est pas correct cette définition, on utilise les tableaux fixes de bytes uniquement pour simuler les chaines de caractères ANSI.
[ StructLayout( LayoutKind.Sequential ) ]
public struct _IPL_INST_CONFIG
{
public uint SN; // 32bits non signé.
public int ID; // 32bits
}
vanisheur
Messages postés9Date d'inscriptionvendredi 18 juillet 2003StatutMembreDernière intervention11 août 2009 10 juin 2009 à 15:57
Je suis embetté , je viens de faire comme tu m'a dit mais je me recupere une exception AccessViolation au moment de l'appel de la fonction, c'est bizzare parcequ'avec les champs de bytes ça le fait pas.
j'ai l'impression que ça tiens a cette difference.
dans un cas les byte[] sont de taille figées et fixed mais avec les uint non
Lutinore
Messages postés3246Date d'inscriptionlundi 25 avril 2005StatutMembreDernière intervention27 octobre 201241 10 juin 2009 à 16:34
Si tu as ça en C
unsigned int SN;
int ID;
Tu ne peux pas mettre ça :
[ StructLayout( LayoutKind.Sequential ) ]
public unsafe struct _IPL_INST_CONFIG
{
public fixed byte SN[ 4 ];
public fixed byte ID[ 2 ];
}
car le INT qu'il soit unsigned ou pas il fait 16 ou 32 bits mais pas 1 fois 16 bits et une fois 32 bits.
---
Les Int en C# sont de taille fixe et fixe en mémoire donc champs de bits ou Int ça ne changera rien.. regarde tout de même si y'a une directive "pragma pack" dans le header C/C++.
vanisheur
Messages postés9Date d'inscriptionvendredi 18 juillet 2003StatutMembreDernière intervention11 août 2009 10 juin 2009 à 18:15
Encore merci pour ta patience,
j'ai suivi tes directives, tu as absolument raison (encore heureux !!),
En fait puisque ma variable SN doit contenir 74406 je suis obligatoirement en presence de la partie 32 bits de ton message.
voici ce que j'ai fait :
j'ai repris mon code et j'ai juste transformé mes 4 champs de bytes en un Uint32 en commentant l'init de la variable et ça compile.
maintenant mon probleme est trés claire, je me perd dans les indirections :
dans le bloc unsafe ou j'appelle la fonction, il faut auparavent que j'ecrive dans le SN 74406 pour que la dll puisse lire ce chiffre.
La façon dont je le fait genere mon acces violation, peut tu m'aider en corrigeant ce que j'ai fait :
la l'ecriture du 74406 genere l'exception alors que si je repasse en champs de byte elle n'est pas levée :
temporairement pour debugger je ne touche qu'au SN, j'ai laissé l'id pour comparer
[StructLayout(LayoutKind.Sequential)]
public unsafe struct _IPL_INST_CONFIG
{
public UInt32 S_N;
public fixed byte ID[2];
}
ssgg
Messages postés1Date d'inscriptionlundi 4 décembre 2000StatutMembreDernière intervention25 novembre 2010 25 nov. 2010 à 15:15
Bonjour,
Je suis en charge d'un "petit" développement en C#. Le but étant d'utiliser une dll C++ dans le code C#. Or, cette dll utilise des pointeurs. Et je n'arrive pas à utiliser les fonctions appelées dans cette dll. Le problème est le passage des pointeurs C++ à C#. Pourriez-vous me donner un coup de main ?
Mon de code C# est le suivant :
- Déclaration de le fonction :
[DllImport("toto.dll")]
public static extern void TT_Initialization(double [] Data, double [] Input, double [] Output, int [] Iesistance, double []Dsistance, int [] IEgeur, double [] DEgeur, int [] Iquage, double [] DPiquage, ref double PrfT, ref double PrfQ, ref double PrfM, ref double PrfD, ref double PrfE, ref double PrfX, ref double PrfY, string [] arMsg, out int iError);