如何使用DllImport将指针(指向doubleArray)从c++代码发送到c#代码(以及从c#发送到c++)
本文关键字:代码 c++ 何使用 DllImport 指针 doubleArray 指向 | 更新日期: 2023-09-27 18:28:43
所以,问题是我有一个double数组,我想通过运行的C++DLL(由我的C#应用程序加载)将其发送到我的C#程序。
我似乎应该使用IntPtr或类似的东西来交换数组或字符串(字符数组),但我真的不知道如何执行。。。
任何人都可以告诉(+示例)向C#/C++代码发送"double[]"或"string"的方法吗?
以下是一些代码作为示例:
C#
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
delegate void FuncPtr([MarshalAs(UnmanagedType.LPArray)] ref double[] dblArr);
[DllImport(dllFilePath, CallingConvention = CallingConvention.Cdecl)]
public static extern void callCSharpFunctionDblArr(IntPtr fctPointer);
public static void printInConsoleDblArr(ref double[] nbArr)
{
Console.Write("value = ");
for(int i=0; i<nbArr.Length; i++)
Console.Write(nbArr[i] + "; ");
Console.WriteLine();
for (int i = 0; i < nbArr.Length; i++)
nbArr[i] = nbArr[i] + 1;
Console.Write("value = ");
for (int i = 0; i < nbArr.Length; i++)
Console.Write(nbArr[i] + "; ");
Console.WriteLine();
}
static void Main(string[] args)
{
FuncPtr printInConsoleDblArrDelegate =
new FuncPtr(printInConsoleDblArr);
IntPtr printInConsoleDblArrPtr =
Marshal.GetFunctionPointerForDelegate(printInConsoleDblArrDelegate);
Console.WriteLine("Second time called from C++ using the call back !!!");
callCSharpFunctionDblArr(printInConsoleDblArrPtr);
Console.ReadLine();
}
C++
__declspec(dllexport) void callCSharpFunctionDblArr( void *fctPointer(double*&) )
{
double* dbl = new double[5];
for(int i=0; i<5; i++)
dbl[i] = (0.5*i);
for(int i=0; i<5; i++)
std::cout << "Before :: dbl[" << i << "] = " << dbl[i] << std::endl;
fctPointer(dbl);
for(int i=0; i<5; i++)
std::cout << "After :: dbl[" << i << "] = " << dbl[i] << std::endl;
}
使用此代码,我得到以下错误::
An unhandled exception of type 'System.AccessViolationException' occurred in ConsoleApplication1.exe
Additional information: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
问题是,当您从C++dll调用回调时,nbArr指向在本机代码中创建的double数组中的第一个值。最好的方法是封送到本机代码和从本机代码封送以获得所需的输出。
若要封送此数据,必须将数组作为IntPtr类型而不是double[]类型传递。您还需要传递数组中元素的数量。通过这种方式,我们处理可以封送的指针。
这是完整的代码:
C#
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
delegate void FuncPtr(ref IntPtr dblArr, int size);
[DllImport("test1dll.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void callCSharpFunctionDblArr(IntPtr fctPointer);
public static void printInConsoleDblArr(ref IntPtr nbArr, int size)
{
// Marshal native to managed
double[] values = new double[size];
Marshal.Copy(nbArr, values, 0, size);
Console.Write("value = ");
for (int i = 0; i < size; i++)
Console.Write(values[i] + "; ");
Console.WriteLine();
for (int i = 0; i < size; i++)
values[i] = values[i] + 1;
Console.Write("value = ");
for (int i = 0; i < size; i++)
Console.Write(values[i] + "; ");
Console.WriteLine();
// Marshal managed to native
Marshal.Copy(values, 0, nbArr, size);
}
static void Main(string[] args)
{
FuncPtr printInConsoleDblArrDelegate =
new FuncPtr(printInConsoleDblArr);
IntPtr printInConsoleDblArrPtr =
Marshal.GetFunctionPointerForDelegate(printInConsoleDblArrDelegate);
Console.WriteLine("Second time called from C++ using the call back !!!");
callCSharpFunctionDblArr(printInConsoleDblArrPtr);
Console.ReadLine();
}
C++
__declspec(dllexport) void callCSharpFunctionDblArr( void *fctPointer(double*&, int size) )
{
double* dbl = new double[5];
for(int i=0; i<5; i++)
dbl[i] = (0.5*i);
for(int i=0; i<5; i++)
std::cout << "Before :: dbl[" << i << "] = " << dbl[i] << std::endl;
fctPointer(dbl, 5);
for(int i=0; i<5; i++)
std::cout << "After :: dbl[" << i << "] = " << dbl[i] << std::endl;
}
您还需要释放在C++本机代码中创建的动态内存。