Как я могу гарантировать, управляемые, комбинированные неуправляемого кода в мой код?
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Runtime.InteropServices; using ReturnCPPArrayToCSharpExample_CSharpSide_; namespace DLLCall { class Program { [DllImport("E:\\C++Projects\\ReturnC++ArrayToDLLExample(1D)\\DLLFromCPPToCSharp\\Debug\\ArrayDLLFromCPPToCSharp")] public static extern IntPtr[] convertMatrix(int height, int width, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(JaggedArrayMarshaler))]byte[][] inputArr); [DllImport("E:\\C++Projects\\ReturnC++ArrayToDLLExample(1D)\\DLLFromCPPToCSharp\\Debug\\ArrayDLLFromCPPToCSharp", CallingConvention = CallingConvention.Cdecl)] public static extern int ReleaseMemory(IntPtr ptr); static void Main(string[] args) { int height = 3; int width = 3; byte[][] inputArr = new byte[3][]; inputArr[0] = new byte[] { 1, 1, 1 }; inputArr[1] = new byte[] { 1, 1, 1 }; inputArr[2] = new byte[] { 1, 1, 1 }; IntPtr[] obj = new IntPtr[3]; obj = convertMatrix(height, width, inputArr); IntPtr[] outputMatrixOfPointers = new IntPtr[3]; //Marshal.Copy(obj, outputMatrixOfPointers, 0, 3); byte[,] result = new byte[3, 3]; //Marshal.Copy(outputMatrixOfPointers, result, 0, 5); for (int i = 0; i < result.Length; i++) { //Console.WriteLine(result[i]); } Console.ReadKey(); } } }
using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; namespace ReturnCPPArrayToCSharpExample_CSharpSide_ { class JaggedArrayMarshaler : ICustomMarshaler { static ICustomMarshaler GetInstance(string cookie) { return new JaggedArrayMarshaler(); } GCHandle[] handles; GCHandle buffer; Array[] array; public void CleanUpManagedData(object ManagedObj) { } public void CleanUpNativeData(IntPtr pNativeData) { buffer.Free(); foreach (GCHandle handle in handles) { handle.Free(); } } public int GetNativeDataSize() { return 4; } public IntPtr MarshalManagedToNative(object ManagedObj) { array = (Array[])ManagedObj; handles = new GCHandle[array.Length]; for (int i = 0; i < array.Length; i++) { handles[i] = GCHandle.Alloc(array[i], GCHandleType.Pinned); } IntPtr[] pointers = new IntPtr[handles.Length]; for (int i = 0; i < handles.Length; i++) { pointers[i] = handles[i].AddrOfPinnedObject(); } buffer = GCHandle.Alloc(pointers, GCHandleType.Pinned); return buffer.AddrOfPinnedObject(); } public object MarshalNativeToManaged(IntPtr pNativeData) { return array; } }
#include <iostream> using namespace std; using byte = unsigned char; extern "C" __declspec(dllexport) unsigned char** convertMatrix(int height, int width, byte inputArr[][3]) { byte** arr = 0; arr = new byte*[height]; for (int i = 0; i < height; i++) { arr[i] = new byte[width]; for (int j = 0; j < width; j++) { arr[i][j] = 0; } } return arr; } extern "C" __declspec(dllexport) int ReleaseMemory(int* pArray) { delete[] pArray; return 0; }
Что я уже пробовал:
Что я уже пробовал:
-Я сам не уверен в этом, но, основываясь на том, что я прочитал, IntPtr[] может использоваться для вызова методов, даже если тип возвращаемого метода отличается, поскольку он может содержать разные объекты, поэтому я чувствовал, что это не должно быть проблемой.
- Добавьте пользовательский класс для маршалирования 2D-массивов, как указано в codeproject as (a.k.a JagggedArrayMarshaller), поскольку я мог понять, что обычные методы маршалинга могут обслуживать только 2D-массив.
- Однако были проблемы, когда я пытался вызвать метод, но я не понимаю, почему маршаллинг неуправляемого кода в управляемый не работает:
IntPtr[] obj = new IntPtr[3]; obj = convertMatrix(height, width, inputArr);
В результате он возвращает ошибку:
Необработанное исключение типа ' System. Runtime.InteropServices.MarshalDirectiveException ' произошло в ReturnCPPArrayToCSharpExample(CSharpSide). exe
Дополнительная информация: невозможно маршалировать "возвращаемое значение": недопустимая комбинация управляемого/неуправляемого типа.