2017-05-08 6 views
1

Je souhaite passer un tableau de structure au plugin natif C++ du script C# unity. J'ai fait comme ci-dessous et je peux accéder aux données, mais mon application se bloque après l'exécution de la fonction C++ et je ne sais pas pourquoi.Passer de grands tableaux de structures du script C# unity à C++ dll en utilisant les plantage de GCHandle après l'exécution de la fonction C++

C# côté:

[StructLayout(LayoutKind.Sequential)] 
    public struct SimpleVector3 
    { 
     public float Vx, Vy, Vz, Nx, Ny, Nz; 

     public SimpleVector3(float x, float y, float z, float xx, float yy, float zz) 
     { 
      Vx = x; 
      Vy = y; 
      Vz = z; 
      Nx = xx; 
      Ny = yy; 
      Nz = zz; 
     } 
    } 

    [DllImport(DLL)] 
     public static extern int getSomeInt(); 

    [DllImport(DLL, CallingConvention = CallingConvention.Cdecl)] 
     public static extern bool PopulateVerts([In] IntPtr verts, int numOfVertices); 

void Start() { 
     Vector3 sceneOrigin = Camera.main.transform.position; 

     Debug.Log("SX " + sceneOrigin.x + " SY " + sceneOrigin.y + " SZ "+ sceneOrigin.z); 

     SimpleVector3[] trial = new SimpleVector3[2]; 
     SimpleVector3 v2 = new SimpleVector3(sceneOrigin.x, sceneOrigin.y, sceneOrigin.z, sceneOrigin.x + 10, sceneOrigin.y + 10, sceneOrigin.z + 10); 
     SimpleVector3 v1 = new SimpleVector3(15,10,3,5,10,6); 
     trial[0] = v1; 
     trial[1] = v2; 
     testing(trial); 
    } 

    void testing(SimpleVector3[] theList) 
     { 
      Debug.Log("the number is " + getSomeInt()); 
      GCHandle pinnedArray = GCHandle.Alloc(theList, GCHandleType.Pinned); 
      IntPtr ptr = pinnedArray.AddrOfPinnedObject(); 
      // call function passing r 
      bool x = PopulateVerts(ptr, theList.Length); 
      Debug.Log("after call " + x); 
      pinnedArray.Free(); 
     } 

côté C++:

extern "C" EXPORT_API int getSomeInt() 
{ 
    return 42; 
} 

extern "C" EXPORT_API bool PopulateVerts(SimpleVector3* verts, int numofVert) { 
    char buffer[50]; 
    for (int i = 0; i < numofVert; i++) { 
     sprintf(buffer, "x %f , y %f , z %f \n nx %f , ny %f , nz %f ", (verts->Vx), 
      (verts->Vy), (verts->Vz), (verts->Nx), (verts->Ny), (verts->Nz)); 
     Debug(buffer); 
     if(i < (numofVert-1)){ 
      verts++; 
     } 
    } 
    return true; 
} 

Le getSomeInt() fonctionne bien et retourne le nombre mais quand il appelle PopulateVerts il affiche les données se bloque alors.

Sortie:

the number is 42 

(Filename: C:/buildslave/unity/build/artifacts/generated/Metro/runtime/DebugBindings.gen.cpp Line: 51) 

CallBack : x 15.000000 , y 10.000000 , z 3.000000 
    nx 5.000000 , ny 10.000000 , nz 6.000000 

(Filename: C:/buildslave/unity/build/artifacts/generated/Metro/runtime/DebugBindings.gen.cpp Line: 51) 

CallBack : x -0.011494 , y 0.069487 , z 0.090230 
    nx 9.988506 , ny 10.069487 , nz 10.090230 

(Filename: C:/buildslave/unity/build/artifacts/generated/Metro/runtime/DebugBindings.gen.cpp Line: 51) 

The program '[2640] dllimporttrial.exe' has exited with code -1073740791 (0xc0000409). 

Ceci est exécuté sur HoloLens. Je ne suis pas sûr de ce que je fais mal et où est exactement l'erreur.

Merci.

Répondre

0

Le problème est probablement dans le type de retour bool ... C++ bool est 1 octet, C# bool est 4 octets.

Essayez:

[DllImport(DLL, CallingConvention = CallingConvention.Cdecl)] 
[return: MarshalAs(UnmanagedType.I1)] 
public static extern bool PopulateVerts([In] IntPtr verts, int numOfVertices); 

Et puis il y a un problème avec la longueur de buffer:

extern "C" EXPORT_API bool PopulateVerts(SimpleVector3* verts, int numofVert) { 
    char buffer[250]; 
    for (int i = 0; i < numofVert; i++) { 
     _snprintf(buffer, 250, "x %f , y %f , z %f \n nx %f , ny %f , nz %f ", (verts->Vx), 
      (verts->Vy), (verts->Vz), (verts->Nx), (verts->Ny), (verts->Nz)); 
     // See the security note at https://msdn.microsoft.com/en-us/library/2ts7cx93(v=vs.71).aspx 
     buffer[sizeof(buffer) - 1] = '\0'; 

     Debug(buffer); 
     if(i < (numofVert-1)){ 
      verts++; 
     } 
    } 
    return true; 
} 
+0

Merci pour votre réponse. J'ai essayé mais ça continue de tomber. En fait je l'ai essayé sans retour aussi, avec du vide avant de poster mais quand même ça plante. –

+0

@AliaAdly Et le 'buffer [50];' est trop petit ... Juste de copier-coller la sortie dans un bloc-notes, il est d'environ 80 caractères. Faites-en environ 200 juste pour être sûr que * et * utilisez le '_snprintf' qui a un paramètre pour la longueur (mais lisez la [note de sécurité] (https://msdn.microsoft.com/en-us/library/2ts7cx93 (v = vs.71) .aspx) si vous utilisez '_snprintf') – xanatos

+0

Merci beaucoup! Ça a marché!! Le problème était en effet dans la taille du buffer! –