Pass large arrays of structs from C# unity script to C++ dll using GCHandle crashes after C++ function execution

2

I want to pass an array of structure to c++ native plugin from C# unity script. I did as below and I can access the data but my application crashes after the c++ function is executed and I am not sure why.

C# side:

[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++ side:

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;
 }

The getSomeInt() is working fine and returns the number but then when it calls PopulateVerts it displays the data then crashes.

Output:

 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).

This is run on HoloLens. I am not sure what am I doing wrong and where exactly is the error.

Thank you.

c#
c++
unity3d
native
asked on Stack Overflow May 8, 2017 by Alia Adly

1 Answer

1

The problem is probably in the return type bool... C++ bool is 1 byte, C# bool is 4 byte.

Try:

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

And then there is a problem with the length of 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;
}
answered on Stack Overflow May 8, 2017 by xanatos • edited May 8, 2017 by xanatos

User contributions licensed under CC BY-SA 3.0