如何在代码中确保托管/非托管组合?

编程入门 行业动态 更新时间:2024-10-28 04:16:52
本文介绍了如何在代码中确保托管/非托管组合?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

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给出(又名JagggedArrayMarshaller),因为我可以理解正常的编组方法只能满足2D数组。 -但是当我试图调用方法但是我不明白为什么会出现问题将托管代码编组到托管代码不起作用:

What I have tried: What I have tried: -I'm not sure about this myself, but based on what I have read, IntPtr[] can be used to invoke methods even if the method return type is different as it could hold different objects, so I felt that should'nt be an issue. -Add in a custom class to marshal 2D-arrays as given from codeproject as (a.k.a JagggedArrayMarshaller) as I could understand that normal marshaling methods could only cater to a 2D array. -However there were issues when I tried to invoke the method but I do not understand why the marshalling to unmanaged code to managed does not work:

IntPtr[] obj = new IntPtr[3]; obj = convertMatrix(height, width, inputArr);

结果,它返回错误: 返回类型'System.Runtime.InteropServices.MarshalDirectiveException'的未处理异常在ReturnCPPArrayToCSharpExample(CSharpSide).exe 附加信息:无法封送'返回value':无效的托管/非托管类型组合。

As a result, it returns the error: An unhandled exception of type 'System.Runtime.InteropServices.MarshalDirectiveException' occurred in ReturnCPPArrayToCSharpExample(CSharpSide).exe Additional information: Cannot marshal 'return value': Invalid managed/unmanaged type combination.

推荐答案

错误是正确的:在C ++运行时分配内存并在C#中使用它不是一个好主意作为对象。 双指针(字节**)毫无意义。使用一个简单的指针。 解决方案:在C#中分配内存并将其作为参数提供给C ++。看看我的文章,它以简单的方式处理这些内容。 BTW:不要使用完整的pathes,而是将dll复制到正确的目录中。这是糟糕的风格,有一天你会崩溃 The error is correct: It is not a good idea to allocate memory in the C++ runtime and use it in C# as object. The double pointers (byte**) making no sense. Use a simple pointer. Solution: allocate in the memory in C# and give it as parameter to C++. Take a look at my article which deals such stuff in a simple way. BTW: dont use complete pathes, but copy the dll in the correct directory. It is bad style and someday you will have crashes

更多推荐

如何在代码中确保托管/非托管组合?

本文发布于:2023-11-02 18:09:18,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1553056.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:组合   代码   如何在

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!