2016-02-19 142 views
-1

我創建了一個C++ .dll庫,用於Unity5 C#程序。使用從DLL的CopyMemory並拋出訪問衝突錯誤

但是,當我從Unity編輯器運行程序並嘗試調用smCopy時,Unity崩潰並嘗試發送錯誤報告;相反,我將該錯誤追蹤爲smCopy發生的訪問衝突錯誤。

.dll文件庫允許我連接到一臺服務器,並通過此功能,將數據複製到一個給定的參數:

C++: 
void DLL_API smCopy(const VOID *dest, SIZE_T len) 
{ 
    CopyMemory((PVOID)(dest), (PVOID)(mapBuffer), len); 
} 

在我的統一腳本,我導入功能:

C#: 
[DllImport(DLL_NAME, EntryPoint = "smCopy")] 
private static extern void smCopyData(IntPtr dest, IntPtr len); 

並最終調用它:

C#: 
{ 
// create IntPtr for message 
    IntPtr msg_intptr = new IntPtr(); 

    smCopyData(msg_intptr, (IntPtr)Marshal.SizeOf(typeof(smMsg))); 

    // create actual data struct 
     // smMsg is a struct referenced in both .dll & Unity script 
    smMsg data_msg = new smMsg(); 

    // Set POINTER data to struct 
    Marshal.PtrToStructure(msg_intptr, data_msg); 
} 

我調試並跟蹤從smCopyData發生的錯誤,與在日誌中找到以下錯誤:

`VCRUNTIME140D.dll caused an Access Violation (0xc0000005) in module VCRUNTIME140D.dll at 0033:b4761c89.` 

.dll文件可與其他功能,我能夠從這個發生錯誤連接到服務器成功,除了。


現在我不知道接下來可以做什麼,因爲我需要這個函數將數據從服務器複製到結構中。

我該如何將內存從服務器(mapBuffer)複製到C#中的參數變量?


Reference to Marshal & IntPtr

Editor.log堆棧跟蹤

0x00007FFBB70A1C89 (VCRUNTIME140D) memcpy 
0x00007FFBB72819D9 (SharedMemoryClientDLL) [l:\projects\google\chapstick\software\working\abner\misc proj\vs\sharedmemoryclientdll\sharedmemoryclientdll\smclibrary.cpp:151] smCopy 
0x0000000012B65B29 (Mono JIT Code) (wrapper managed-to-native) SMCScript:smCopyData (intptr,intptr) 
0x0000000012B65793 (Mono JIT Code) [L:\Projects\Google\chapstick\Software\Working\Abner\Misc Proj\Unity\ChapstickProject\Assets\Scripts\SMCScript.cs:202] SMCScript:GetData() 
0x0000000012B62CA3 (Mono JIT Code) [L:\Projects\Google\chapstick\Software\Working\Abner\Misc Proj\Unity\ChapstickProject\Assets\Scripts\SMCScript.cs:176] SMCScript:CheckForEvent() 
0x0000000010B69232 (Mono JIT Code) [L:\Projects\Google\chapstick\Software\Working\Abner\Misc Proj\Unity\ChapstickProject\Assets\Scripts\SMCScript.cs:150] SMCScript:Update() 
0x00000000007D68E2 (Mono JIT Code) (wrapper runtime-invoke) object:runtime_invoke_void__this__ (object,intptr,intptr,intptr) 
0x00007FFB9B5F41BF (mono) [c:\buildslave\mono-runtime-and-classlibs\build\mono\mini\mini.c:4937] mono_jit_runtime_invoke 
0x00007FFB9B548435 (mono) [c:\buildslave\mono-runtime-and-classlibs\build\mono\metadata\object.c:2623] mono_runtime_invoke 
0x000000014033E20F (Unity) scripting_method_invoke 
+0

那麼,看看C++代碼,這不是問題。所以它必須是你如何編組/接口到C#中的函數# – PaulMcKenzie

+0

在將它傳遞給C++ DLL之前,你不需要先創建一個緩衝區嗎?我確信創建一個IntPtr()不會這樣做。 – PaulMcKenzie

+0

我很確定這是*問題,並且您未能爲將要複製數據的緩衝區分配內存。如何在C#中做到這一點 - 你需要做的研究。只是創建一個IntPtr()什麼也不做。 – PaulMcKenzie

回答

0

您需要分配一個緩衝區,它的指針傳遞給函數。您只是傳遞一個空指針,以便cpp函數正在嘗試寫入地址0,這會導致訪問衝突異常。

var len = Marshal.SizeOf(typeof(smMsg)); 
IntPtr msg_intptr = Marshal.AllocHGlobal(len); 
try { 
    // call the function, convert output to struct, etc... 
} 
finally { 
    Marshal.FreeHGlobal(msg_intptr); 
} 
+0

非常感謝!我誤解了IntPtr的確切使用和實現,但我現在看到了。 – Abner