gregcedepe
Messages postés6Date d'inscriptionjeudi 11 octobre 2007StatutMembreDernière intervention11 avril 2008
-
2 avril 2008 à 18:47
olibara
Messages postés666Date d'inscriptiondimanche 16 décembre 2007StatutMembreDernière intervention11 mars 2010
-
11 avril 2008 à 21:37
Bonjour,
J'apelle une dll à l'intérieur d'un programme c#.
Les fonctions les plus simples retournant un booléen fonctionnent bien et je récupère bien le booléen en retour.
Là où ça se complique c'est que une fonction retourne un pointeur. Lorsque la fonction me retourne le pointeur, j'ai un bug (accès à des mémoires protégées). J'ai un programme en C qui fonctionne avec cette fonction et mon programme en c# lui ne fonctionne pas.
Extrait du programme en C (qui fonctionne):
////////Déclaration dans un .h:
MOCRAPI_USAGE
olibara
Messages postés666Date d'inscriptiondimanche 16 décembre 2007StatutMembreDernière intervention11 mars 20106 5 avril 2008 à 08:02
Il n'est pas non plus impossible que cette dll utilise un contexte mal défini et que le plantage ne vienne pas du tout de la manipulation du pointeur en entrée mais d'une autre opération interne
- ouverture ou ecriture de fichier ?
- acces a une ressource
- etc...
olibara
Messages postés666Date d'inscriptiondimanche 16 décembre 2007StatutMembreDernière intervention11 mars 20106 3 avril 2008 à 08:05
Bonjour,
Je viens de resoudre un problème plus complexe mais similaire
Il faut considerer que tout pointeur dans une DLL c doit etre passé en tant que IntPtr en cSharp
La conversion se fera apres
Et pour bien isoler le code manage csharp et l'environnement dll, j'emballe l'appel dll dans une fonction qui s'occupera de toute la gestion des conversion
Je ne peux pas deviner a qoui sert exactement lenDatasz, mais si ta fonction rend un char * sur un string terminé par un null char, a mon avis tu devrais essayer ceci
("mOcrApi_dbg.dll", CharSet= CharSet.Auto
)]
public unsafe static extern bool ScanAndRecognize(ref IntPtr cData, int nDataSz
);
gregcedepe
Messages postés6Date d'inscriptionjeudi 11 octobre 2007StatutMembreDernière intervention11 avril 2008 3 avril 2008 à 10:49
J'ai essayé d'intégrer IntPtr. Le programme compile mais la dll plante toujours au retour. J'ai toujours le message : "Tentative de lecture ou d'écriture de mémoire protégée. Cela indique souvent qu'une autre mémoire est endommagée."
Peut-être y a t-il une erreur au niveau de mon code :
//Déclarations :
public
IntPtr cData
;
[DllImport("mOcrApi_dbg.dll", CharSet
= CharSet
.Auto
)]
public unsafe static extern bool ScanAndRecognize(ref IntPtr cData
, int nDataSz
);
gregcedepe
Messages postés6Date d'inscriptionjeudi 11 octobre 2007StatutMembreDernière intervention11 avril 2008 3 avril 2008 à 14:08
Vu le code en C qui fonctionne, je pense effectivement que la dll recopie dans cData un truc de la longueur nDataSz. Je pense aussi que ce n'est pas cette interprétation là que je fais dans mon programme c#.
Dans ce cas là, comment faire l'équivalent du memset en c#?
olibara
Messages postés666Date d'inscriptiondimanche 16 décembre 2007StatutMembreDernière intervention11 mars 20106 3 avril 2008 à 14:54
Dans ce genre de truc je travaille par essai erreur pour essaye de faire comprendre au compilo ce que je lui passe et ce qu'il doit me rendre
Et a vrai dire si c'est vraiment une recopie dans ta dll je comprends pas bien pourquoi le premier exemple que tu a donné ne marche pas. Essaye de reduire le size que tu lui donne!
Sinon j'ai vu un truc un peu plus sophistiqué que tu pourrais adapter, ici on passe un tableau de string mais tu pourrais te contenter d'un UnmanagedType.LPWStr
olibara
Messages postés666Date d'inscriptiondimanche 16 décembre 2007StatutMembreDernière intervention11 mars 20106 4 avril 2008 à 07:40
Salut Lutinore
Bien sur tu a raison sur certains points et j'ai bien dis qu'il fallait adapter le code que j'avais trouvé
C'est clair que si la DLL recopie elle meme un string sur le pointeur qu'on lui passe on ne peut pas lui passer un pointeur null
Mais dans cette assertion, le premier code montré n'a aucune raison de planter, que ce soit byte ou char ou unicode etc.. pratiquement elle recopie 99 byte dans un tableau de 100
Maintenant si c'est un problème de longueur (pour une raison a determiner) gregcedepe peut jouer sur sa declaration et l'appel (d'ailleurs je vois qu'en c il dimensionne a 1000)
si par contre la dll chipote le pointeur passé l'exemple que j'ai montré permetrait de le voir.
gregcedepe
Messages postés6Date d'inscriptionjeudi 11 octobre 2007StatutMembreDernière intervention11 avril 2008 4 avril 2008 à 17:12
Merci pour vos réponses. Je pense que le problème est effectivement le traitement d'un char sur 1 octet par un programme qui attend un char à 2 octets. Est-ce que le fait d'utiliser CharSet= CharSet.Ansi
doit résoudre tout le problème. En effet, le programme suivant me retourne le même problème:
//Déclaration
[ DllImport
("mOcrApi_dbg.dll", CharSet
=CharSet
.Ansi
)]
public unsafe static extern bool ScanAndRecognize(char *cData
, int nDataSz
);
//Appel
bool bool1
;
unsafe
{
char[] mrz_data = new char [1000];
fixed (char* mrz = mrz_data)
//memset(cMrzData, NULL, sizeof(cMrzData));
bool1 = ScanAndRecognize (mrz, 999);
// Print the result
for (int i = 0 ; i<=100 ; i++)
{
//if (cMrzData[i] != '\r')
textBox1.Text = textBox1.Text + mrz_data[i];
}
}
J'ai aussi essayé de récupérer du type byte (1 octet):
gregcedepe
Messages postés6Date d'inscriptionjeudi 11 octobre 2007StatutMembreDernière intervention11 avril 2008 11 avril 2008 à 18:31
Merci pour vos réponses.
J'ai trouvé mon erreur. Il fallait envoyer une commande Initialize() inclue dans l'API de mon composant avant de lui envoyer une demande de scan, comme pour le préparer à envoyer des données. Ce forum m'a cependant aidé pour ce qui est de la conversion du char 1 octet en char 2 octet : je passe par un type byte puis je fais un cast vers du char.
olibara
Messages postés666Date d'inscriptiondimanche 16 décembre 2007StatutMembreDernière intervention11 mars 20106 11 avril 2008 à 21:37
Super !
Je suis content que ca marche et que mon intuition n'était pas fausse !
Je connais bien ce type de bug et j'appelle ca le syndrome du réverbère : dans le noir on cherche la ou il y a un peu de lumière mais on néglige plus facilement l'ombre
Dans ton cas il etait evidement aisé de penser que le probleme venait de l'appel et de la maniere de passer les parametres mais moins évident de jeter un coup d'oeil su le contexte géneral !