Использование CopyMemory из dll и выдача ошибки нарушения прав доступа

Я создал библиотеку .dll C ++ для использования в программе Unity5 C #.

Однако, когда я запускаю программу из редактора Unity и пытаюсь вызвать smCopy, Unity вылетает и пытается отправить отчет об ошибке; вместо этого я отследил, что это ошибка нарушения прав доступа, происходящая из smCopy.

Библиотека .dll позволяет мне подключаться к серверу и копировать данные в заданный параметр с помощью этой функции:

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

В моем скрипте Unity я импортирую функцию:

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 #?


Ссылка на 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

person Abner    schedule 19.02.2016    source источник
comment
Что ж, если посмотреть на код C ++, проблема не в этом. Так что это должно быть то, как вы маршалируете / взаимодействуете с функцией из C #.   -  person PaulMcKenzie    schedule 20.02.2016
comment
Разве вам не нужно сначала создать буфер, прежде чем передавать его в C ++ DLL? Я уверен, что создание IntPtr () этого не сделает.   -  person PaulMcKenzie    schedule 20.02.2016
comment
Я почти уверен, что это проблема, и что вы не смогли выделить память для буфера, в который вы собираетесь копировать данные. Как это сделать на C # - вам нужно провести исследование. Простое создание IntPtr () ничего не делает.   -  person PaulMcKenzie    schedule 20.02.2016
comment
Да, теперь понятно! Большое спасибо за отзыв, я плохо разбирался в IntPtr.   -  person Abner    schedule 22.02.2016


Ответы (1)


Вам нужно выделить буфер и передать его указатель функции. Вы просто передаете пустой указатель, поэтому функция 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);
}
person Mehrzad Chehraz    schedule 19.02.2016
comment
Большое спасибо! Я неправильно понял точное использование и реализацию IntPtr, но теперь понимаю. - person Abner; 22.02.2016