如何使用 DLL 从 C++/C 获取数组到 C#
How to get array from C++/C to C# using DLL
我是 C# 和 C/C++ 的新手。我用 C 编写了一个代码,将 2 个变量存储在一个数组中,return 数组。使用 P/invoke 方法我创建了这个 C 函数的 DLL 库并将该库导入到 C#。调用数组时,我无法从 C# 中获取数组。
需要您的帮助。这是 C 代码
#include <stdio.h>
extern __declspec(dllexport) int* sum();
int* sum()
{
int a = 50, b = 80, sum, neg;
sum = a + b;
neg = b - a;
int arr[2] = { sum, neg };
return arr;
}
现在 C# 代码是...
using System;
using System.Runtime.InteropServices;
namespace ConsoleApplication
{
class Program
{
[DllImport("Project2.dll")]
unsafe public static extern int* sum();
static void Main(string[] args)
{
unsafe
{
int* array2 = sum();
Console.WriteLine("Value: " + array2[0]);
}
}
}
}
请告诉我如何获取数组。
return数组有多种方法,但在所有情况下您都必须解决两个问题:
- 能够告诉 .NET 数组中项目的数量;
- 为本机和 .NET 大小使用通用内存分配器。选择的分配器是 COM 分配器,因为它是 known to .NET;
以下是两个使用 .NET 安全代码的示例:
本机代码 1:
extern __declspec(dllexport) SAFEARRAY * sumSafeArray()
{
int a = 50, b = 80, sum, neg;
sum = a + b;
neg = b - a;
int arr[2] = { sum, neg };
// SAFEARRAY is a OLE/COM automation type well known to Windows and .NET
// (note it implicitly uses the COM allocator too)
SAFEARRAY* psa = SafeArrayCreateVector(VT_I4, 0, 2);
void* data;
SafeArrayAccessData(psa, &data);
CopyMemory(data, arr, sizeof(arr));
SafeArrayUnaccessData(psa);
return psa;
}
托管代码 1:
[DllImport("mydll")]
[return: MarshalAs(UnmanagedType.SafeArray)]
private static extern int[] sumSafeArray();
foreach (var i in sumSafeArray())
{
Console.WriteLine(i);
}
本机代码 2:
extern __declspec(dllexport) void sumArray(int** out, int* count)
{
int a = 50, b = 80, sum, neg;
sum = a + b;
neg = b - a;
int arr[2] = { sum, neg };
// always use COM allocator
*out = (int*)CoTaskMemAlloc(sizeof(arr));
CopyMemory(*out, arr, sizeof(arr));
*count = sizeof(arr) / sizeof(int);
}
托管代码 2:
[DllImport("mydll")]
private static extern void sumArray(out IntPtr array, out int size);
sumArray(out var ptr, out var size);
var ints = new int[size];
Marshal.Copy(ptr, ints, 0, size);
Marshal.FreeCoTaskMem(ptr);
foreach (var i in ints)
{
Console.WriteLine(i);
}
还有一个使用 .NET 不安全代码的示例:
本地代码:
extern __declspec(dllexport) int* sum(int* count)
{
int a = 50, b = 80, sum, neg;
sum = a + b;
neg = b - a;
int arr[2] = { sum, neg };
// always use COM allocator
int* out = (int*)CoTaskMemAlloc(sizeof(arr));
CopyMemory(out, arr, sizeof(arr));
*count = sizeof(arr) / sizeof(int);
return out;
}
托管代码:
[DllImport("mydll")]
private unsafe static extern int* sum(out int count);
var ints = sum(out var count);
for (var i = 0; i < count; i++)
{
Console.WriteLine(*ints);
ints++;
}
您也可以使用另一个分配器(new/malloc/custom,等等),但在这种情况下,您需要 expose/export 到 .NET 相应的“free”方法,并在需要时自己执行 free .
我是 C# 和 C/C++ 的新手。我用 C 编写了一个代码,将 2 个变量存储在一个数组中,return 数组。使用 P/invoke 方法我创建了这个 C 函数的 DLL 库并将该库导入到 C#。调用数组时,我无法从 C# 中获取数组。 需要您的帮助。这是 C 代码
#include <stdio.h>
extern __declspec(dllexport) int* sum();
int* sum()
{
int a = 50, b = 80, sum, neg;
sum = a + b;
neg = b - a;
int arr[2] = { sum, neg };
return arr;
}
现在 C# 代码是...
using System;
using System.Runtime.InteropServices;
namespace ConsoleApplication
{
class Program
{
[DllImport("Project2.dll")]
unsafe public static extern int* sum();
static void Main(string[] args)
{
unsafe
{
int* array2 = sum();
Console.WriteLine("Value: " + array2[0]);
}
}
}
}
请告诉我如何获取数组。
return数组有多种方法,但在所有情况下您都必须解决两个问题:
- 能够告诉 .NET 数组中项目的数量;
- 为本机和 .NET 大小使用通用内存分配器。选择的分配器是 COM 分配器,因为它是 known to .NET;
以下是两个使用 .NET 安全代码的示例:
本机代码 1:
extern __declspec(dllexport) SAFEARRAY * sumSafeArray()
{
int a = 50, b = 80, sum, neg;
sum = a + b;
neg = b - a;
int arr[2] = { sum, neg };
// SAFEARRAY is a OLE/COM automation type well known to Windows and .NET
// (note it implicitly uses the COM allocator too)
SAFEARRAY* psa = SafeArrayCreateVector(VT_I4, 0, 2);
void* data;
SafeArrayAccessData(psa, &data);
CopyMemory(data, arr, sizeof(arr));
SafeArrayUnaccessData(psa);
return psa;
}
托管代码 1:
[DllImport("mydll")]
[return: MarshalAs(UnmanagedType.SafeArray)]
private static extern int[] sumSafeArray();
foreach (var i in sumSafeArray())
{
Console.WriteLine(i);
}
本机代码 2:
extern __declspec(dllexport) void sumArray(int** out, int* count)
{
int a = 50, b = 80, sum, neg;
sum = a + b;
neg = b - a;
int arr[2] = { sum, neg };
// always use COM allocator
*out = (int*)CoTaskMemAlloc(sizeof(arr));
CopyMemory(*out, arr, sizeof(arr));
*count = sizeof(arr) / sizeof(int);
}
托管代码 2:
[DllImport("mydll")]
private static extern void sumArray(out IntPtr array, out int size);
sumArray(out var ptr, out var size);
var ints = new int[size];
Marshal.Copy(ptr, ints, 0, size);
Marshal.FreeCoTaskMem(ptr);
foreach (var i in ints)
{
Console.WriteLine(i);
}
还有一个使用 .NET 不安全代码的示例:
本地代码:
extern __declspec(dllexport) int* sum(int* count)
{
int a = 50, b = 80, sum, neg;
sum = a + b;
neg = b - a;
int arr[2] = { sum, neg };
// always use COM allocator
int* out = (int*)CoTaskMemAlloc(sizeof(arr));
CopyMemory(out, arr, sizeof(arr));
*count = sizeof(arr) / sizeof(int);
return out;
}
托管代码:
[DllImport("mydll")]
private unsafe static extern int* sum(out int count);
var ints = sum(out var count);
for (var i = 0; i < count; i++)
{
Console.WriteLine(*ints);
ints++;
}
您也可以使用另一个分配器(new/malloc/custom,等等),但在这种情况下,您需要 expose/export 到 .NET 相应的“free”方法,并在需要时自己执行 free .