2017-05-08 46 views
1

我想從C#統一腳本向C++本機插件傳遞一個結構數組。我做了如下,我可以訪問數據,但我的應用程序崩潰C++函數執行後,我不知道爲什麼。將C#統一腳本中的大型數組結構傳遞給C++ dll使用GCHandle在C++函數執行後崩潰

C#側:

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

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

的getSomeInt()工作正常,並返回的數量,但然後當它調用PopulateVerts它顯示然後崩潰的數據。

輸出:

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

這是HoloLens運行。我不確定我做錯了什麼,錯誤到底在哪裏。

謝謝。

回答

0

問題可能出在返回類型bool ... C++ bool是1字節,C#bool是4字節。

嘗試:

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

再有就是與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

感謝您的答覆。我嘗試過,但仍然崩潰。其實我也嘗試過,沒有回報,發帖之前沒有回覆,但仍然崩潰。 –

+0

@AliaAdly而'buffer [50];'太小了......只是將輸出複製粘貼到記事本上,它大約有80個字符。使其大約爲200,以確保*和*使用具有長度參數的_snprintf'(但請閱讀[安全說明](https://msdn.microsoft.com/zh-cn/library/2ts7cx93( v = vs.71).aspx)如果使用'_snprintf') – xanatos

+0

非常感謝!有效!!問題的確在於緩衝區的大小! –