Вы должны сначала полностью прочитать эту статью: https://docs.microsoft.com/en-us/dotnet/framework/interop/default-marshaling-for-arrays#unmanaged -arrays
Я также нашел это соответствующие QAs: Как создать и инициализировать SAFEARRAY для двойников в C ++ для передачи в C#
Ваша GetCppArray
функция возвращает только указатель - она не возвращает самоописываемый «безопасный» массив, тогда как массивы в. NET включают длину и ранг (измерение ), поэтому вам определенно необходимо изменить код C ++, чтобы сделать это правильно.
Первый вариант - вернуть массив в виде безопасного массива в стиле COM * , это делается с помощью макрос SAFEARRAY( typename )
- и он должен передаваться как параметр, а не возвращаемое значение.
Существует два основных способа использования COM Safe-Arrays в C ++: использование таких функций Win32, как SafeArrayCreate
- которые больно использовать правильно, или используя ATL CComSafeArray
.
(Отказ от ответственности: я написал этот код, просматривая ссылки на API, я не проверил это - я даже не знаю, скомпилируется ли он).
// C++ code for SafeArrayCreate:
#include <comdef.h>
int test_data[5] = { 12, 60, 55, 49, 26 };
extern "C" __declspec(dllexport) HRESULT GetCppArray( [out] SAFEARRAY( int )** arr )
{
SAFEARRAYBOUND bounds;
bounds.lLbound = 0;
bounds.cElements = sizeof(test_data);
*arr = SafeArrayCreate(
VT_I4, // element type
1, // dimensions
&bounds
);
if( !arr ) {
// SafeArrayCreate failed.
return E_UNEXPECTED;
}
int* arrPtr;
HRESULT hr = SafeArrayAccessData( *arr, &arrPtr );
if( !SUCCEEDED( hr ) ) {
hr = SafeArrayDestroy( arr );
// After SafeArrayDestory, if `hr != S_OK` then something is really wrong.
return E_UNEXPECTED;
}
for( size_t i = 0; i < sizeof(test_data); i++ ) {
*arrPtr[i] = test_data[i];
}
hr = SafeArrayUnaccessData( *arrPtr );
if( !SUCCEEDED( hr ) ) {
hr = SafeArrayDestroy( arr );
return E_UNEXPECTED;
}
return S_OK;
}
Затем необходимо обновить C# код, чтобы объявить, что он возвращает SafeArray
:
// HRESULT is best represented as a UInt32 instead of Int32.
[DllImport( "CppDll.dll", CallingConvention = CallingConvention.Cdecl )]
public static extern UInt32 GetCppArray(
[MarshalAs( UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_I4 )] out Int32[] arr
);