2010-11-14 17 views
0

Si je veux appeler une fonction C++ externe qui retourne un tableau 2d, quel genre de problèmes pourrais-je rencontrer? Par exemple, si je déclare le tableau 2D à l'intérieur de la fonction C++ et initialise la taille du tableau dans la fonction C++, comment le garbage collector automatique .Net va-t-il gérer cela? Dois-je lui donner une fonction qui effectue la collecte des ordures et si oui, comment puis-je l'appeler à partir d'un programme C#?Tableaux 2D inter-langages C++ et C#

Répondre

2

À moins que la fonction retourne un vecteur ou des vecteurs, il est l'exacte même problème en C++ ainsi. C'est un problème de gestion de la mémoire, l'appelant de la fonction n'a aucun bon moyen de libérer la mémoire du tableau, il ne connaît pas la taille des tableaux ni l'allocateur utilisé. D'ailleurs, même itérer le tableau est périlleux. Un problème que vous ne pouvez pas corriger en C++ ne peut pas non plus être résolu dans interop géré.

Et vous le résolvez de la même manière, vous laissez l'appelant fournir le tableau, à remplir par l'appelé.

Notez que les tableaux gérés n'ont pas ce problème, ils sont des classes tout comme le vecteur <>. Le retour d'un tableau géré à partir d'une fonction n'est pas un problème. C++/CLI peut le faire, la solution standard pour les problèmes d'interopérabilité difficiles. Un SAFEARRAY est également une solution, informez-en le P/Invoke marshaller à propos de lui avec [MarshalAs] dans la déclaration managée.

+0

Merci, c'était très perspicace!En passant, j'ai lu à ce sujet mais je ne suis pas sûr de savoir ce que l'on entend quand on parle de code C++ géré/non géré. –

+0

Il n'existe pas de code C++ géré. Le langage C++/CLI ressemble à la syntaxe C++. Son compilateur est capable d'analyser le code C++ * et * d'analyser les classes managées. –

0

comment le collecteur d'ordures automatique de .Net manipulera ceci?

Cela n'aura rien à voir avec la mémoire allouée par les applications natives. Vous pouvez renvoyer une copie du tableau au module C# et cela prend soin de ce problème. Si c'est très grand et que ça serait un problème ... eh bien, peut-être que quelqu'un d'autre a une meilleure suggestion car je n'ai pas encore eu à traverser ce pont =). Vous l'alloueriez probablement et le détruiriez dans le code C++ et retourneriez un pointeur au module C#. Attention à cela, et comme je l'ai dit, je n'ai pas eu à faire une telle chose.

0

Je sais que pour les types simples, comme une chaîne, l'interop fera une copie de l'objet non géré et le ramènera à l'appelant. À ce stade, le CLR tentera de nettoyer la mémoire avec un appel à CoTaskMemFree(). Que cela réussisse ou non dépend de la façon dont la mémoire a été allouée. Si vous le pouvez, utilisez CoTaskMemAlloc() pour allouer de la mémoire, ce qui permettra à l'appel à CoTaskMemFree() de réussir. J'ai lu qu'un échec de libérer la mémoire se traduira par une fuite sur XP, mais lèvera une exception dans Vista et Win7 ... ne peut pas parler de la validité de cela.

Pour les types plus compliqués, tels qu'un tableau, je ne suis pas sûr que cela soit vrai. Cependant, une excellente méthode pour libérer de la mémoire est dans un article here. L'essentiel est de repasser les données en IntPtr, puis d'exposer une méthode de la DLL appelée FreeMemory(), qui prend IntPtr et libère la mémoire qui y est allouée.

HTH,
James

+0

Le nom 'FreeMemory' n'a rien de spécial, et l'écrire n'est pas suffisant car C#/.NET ne l'appellera pas automatiquement. Ecrire une fonction pour libérer le tableau, lui donner un nom de votre choix, et l'appeler à partir du code C# quand il n'a plus besoin d'utiliser le tableau. –

+0

Ben> Vous avez raison, je l'ai juste appelé arbitrairement ... la clé est que c'est une méthode que vous écrivez pour libérer la mémoire ... il n'y a rien de intégré. –