[C#] COM Marshaling vers un type à la con

Yo la zone,

J’ai un petit problème avec un activex COM que j’utilise dans une appli C#, et je n’arrive pas à le résoudre.

Cet activex possède une méthode GetList() avec la signature suivante :

short GetList(unsigned char* lpList);

La méthode getList peuple la liste passée en paramètre avec des chaînes, et renvoie le nombre d’éléments ajoutés.

Et je vous file l’exemple C++ unmanaged qu’on m’a donné :

[code]#define MAXLEN 32

struct TN{
char name[MAXLEN];
};

void toto(int nbRec)
{
short nbNames = m_Toto.GetNb();
TN *pList = new TN[nbNames];

short nbReal = m_Toto.GetList((unsigned char*)(pList));
}[/code]

PS: De ce que j’en ai compris, en mattant l’exemple, c’est que pList est en fait une chaîne découpée en sous-chaînes par le biai d’une structure. J’en ai déduit qu’on aurait pu faire char[] pList = char[MAXLEN * nbNames]; avec le même résultat.

Bref…

Première étape en C# : génération des librairies avec tlbimp.

Je regarde la signature des méthodes générées : il m’a transformé GetList() en GetList(ref byte).

Forcément, impossible pour moi de passer quelque chose qui fonctionne à une telle méthode : il a interprété le unsigned char * comme un « caractère non signé passé par référence » au lieu d’une « chaine de caractère (non signée) ».

Après pas mal de recherche, je me dis que finalement ca doit venir du tlbimp qui n’arrive pas à comprendre ce typage… Donc je rassemble mon courage, je prends ildasm et ilasm, et entreprend de modifier le code IL de mon proxy.

Je cherche un type à utiliser qui soit compréhensible par la méthode, et je dois vous avouer que je cherche encore : je prends un « Type mismatch. (Exception from HRESULT: 0x80020005 (DISP_E_TYPEMISMATCH)) » à chaque fois. Voici 2 typages que j’ai essayé :

  • « string marshal(BSTR) » ne fonctionne pas.
  • « native int » (donc IntPtr) non plus.
  • « byte[] » non plus.

Je fais tout ce que je peux pour que le mec qui a fait cet activex change la signature de sa méthode (vu qu’il ne s’agit au final « que » d’une chaîne de caractère… Mais j’ai peu espoir, et j’en suis donc réduit à trouver une solution pour que ma Lib « tunée » puisse appeller cette &@]! de méthode…

Je m’en remets à ceux qui tâtent peut-être un peu plus que moi en marshaling pour trouver une soluce à mon cas.

Merci :stuck_out_tongue:

Bon, on continue, j’ai trouvé qq trucs sous google (en cherchant unsigned char *).

Ici un exemple d’appel d’une méthode non managée prenant un unsigned char * depuis du managé c++

[code]int FuncA([Out] Byte image __gc[])

{
Byte __pin * test; // __pin extension is a must

test = &image[0]; // point the pointer to the array 1st index which is 0
return _UnmanagedClass->UFuncA(test); // when you press -> it will show the intellisense and display all the unmanaged C++ exposed functions
}[/code]

Mais impossible de faire un tel truc en c#. j’en reviens à mon ref byte comme typage du paramètre, mais je n’arrive pas à bidouiller mon byte[] pour pouvoir le passer en paramètre. (je crois que le mieu que j’ai obtenu pour cela, c’est de récupérer le premier caractère).

Allez, je continue à avancer sur mon malheur…

Voilà un morceau de code qui fonctionne presque :

[code] unsafe
{
int nbUsers = m_Toto.GetNb();
int size = nbUsers * 32 * sizeof(char);

			byte* buff = stackalloc byte;

			short nbUser = m_Toto.GetList(ref test[0]);
		}[/code]

Problème : la fonction ne modifie que le premier élément (mais il le renseigne correctement : j’ai reconnu la première lettre, c’est bien celle que j’attends), elle ne remplit pas le reste (qui est pourtant correctement alloué : la mémoire est bien à 0x00 pour l’ensemble du tableau).