9
votes

Passage de la struct de manière non gérée C ++ à c #

Remarque: strong> La solution de travail finale est après la modification!

J'espère que quelqu'un peut m'aider avec un problème que j'ai essayé de résoudre ces derniers jours. P>

J'essaie de passer une structure d'une dll c ++ non gérée à un script C #. C'est ce que j'ai jusqu'à présent: p>

c ++ p> xxx pré>

c # p> xxx pré>

Le problème est Que cela fonctionne, mais la valeur imprimée est complètement éteinte (parfois elle imprime environ 400, parfois une valeur int tout max). P>

Je suppose qu'il y a quelque chose qui ne va pas avec la structure de la structure en C #. Toutes idées? P>

EDIT: strong> p>

Il s'agit de la solution de travail utilisant REF: P>

C ++ P>

[DllImport ("ArucoUnity")] 
    public static extern void detectMarkers( ... ,
        [MarshalAs(UnmanagedType.Struct)] ref MarkerStruct markerStruct);

...

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public struct MarkerStruct
{
    public int Id;
}

...

detectMarkers (d, W, H, d.Length, ref markerInfo);      
print( markerInfo.Id );


0 commentaires

3 Réponses :


3
votes

La variable markerinfo est locale et dépasse la portée lorsque la fonction renvoie. Ne retournez pas les pointeurs vers les variables locales, les objets qu'ils indiquent n'existeront plus.


1 commentaires

Merci! Avez-vous une suggestion sur ce que je devrais faire à la place?



6
votes

Vous retournez un pointeur sur une variable locale qui a déjà été détruite avant que .NET ne puisse la lire. C'est une mauvaise idée de Pure C ++ et une mauvaise idée avec p / invoke.

Au lieu de cela, avez-vous que C # passe un pointeur à une structure (utilisez simplement le mot-clé ref ) et le code C ++ vient de le remplir.


4 commentaires

J'ai essayé d'utiliser Ref, mais je n'ai toujours pas réussi à obtenir la bonne valeur ... Pourriez-vous avoir un coup d'œil à ma question modifiée?


@kolarek: Comme je l'ai dit dans ma réponse, lorsque vous utilisez le ref ou out le mot clé c # passera réellement un pointeur. Ainsi, utilisez détecteurs de détecteurs (/*...*/1/1/1/19 / code> sur le côté C ++, puis MarkerInfo-> ID = 3; . Également, éloignez-vous de l'attribut dans dans la signature P / invoke, ce qui signifie de ne pas récupérer des données de C ++, ce qui est évidemment le contraire de ce que vous voulez.


Merci beaucoup, je l'ai eu et couru!


@kolarek: Heureux d'entendre ça. Si cette réponse a résolu votre problème, vous cliquez sur la case Hollow à sa gauche pour que les futurs visiteurs savent que c'était la bonne solution. En outre, très agréable de vous voir ajouter le code de travail à votre question.



0
votes

va donner à cela un tourbillon ... THX pour le message ...

// new struct and generic return for items to 
struct  _itemStruct
{
    unsigned int id; // 0 by default, so all lists should start at 1, 0 means unassigned
    wchar_t *Name;
};

// for DLL lib precede void with the following... 
// EXPORT_API 
void getItems(std::vector<_itemStruct *> *items)
{
    // set item list values here


    //unsigned char *bytePtr = (unsigned char*)&items; // manual pointer return

    return;
};

/* // In theory c# code will be...
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public struct _itemStruct
{
    public unsigned int Id;
    public string Name;
}

[DllImport ("ListOfItems")] // for ListOfItems.DLL
public static extern void getItems(
[MarshalAs(UnmanagedType.Struct)] ref List<_itemStruct> items);
// */


0 commentaires