我刚刚加入该网站,这是我在这里的第一个帖子。我真的可以从我的C#应用程序中调用非托管DLL函数的帮助下完成工作。我一直在搜索,发现了各种类似的问题,但是没有什么完全符合我的需求。
我需要调用的函数是:
int DevConfig(struct A *a, int b, unsigned int c, BOOL *d);
其中A定义为:
struct A
{
double f[4];
unsigned int df[4];
unsigned int dfn[4];
double *dc[4];
float dg[4];
float g;
UCHAR gs;
};
我对如何在C#中处理此问题感到困惑和困惑。我认为我需要做这样的事情,但是我知道这不太正确:
[StructLayout(LayoutKind.Sequential)]
public struct A
{
public double[] f = new double[4];
public uint[] df = new uint[4];
public uint[] dfn = new uint[4];
public double[,] dc = new uint[4,256];
public float[] dg = new float[4];
public float g;
public byte gs;
}
[DllImport("DevControl.dll")]
static extern int DevConfig (ref A a, int b, uint c, bool[] d);
我认为这是正确的方法,但是我对double的指针数组(double * dc [4])和布尔数组的指针(BOOL * d)感到困惑。请有人可以帮我解决这个问题吗?
编辑更多信息:使用此功能时,数据从C#流到DLL。也就是说,C#分配内存。我一直在考虑按如下方式指定dc,除非更容易用另一种方式做到这一点:
double[,] dc = new double[4, 256];
该数组的大小始终为4 x256。以某种方式需要将其编组到结构的IntPtr []字段中吗?
对于布尔数组:
bool[] d = new bool[8];
该数组的长度可以变化,不一定总是8(但是DLL通过传入的其他参数之一知道它有多长)。
该结构应如下所示:
public struct A
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst=4)]
public double[];
[MarshalAs(UnmanagedType.ByValArray, SizeConst=4)]
public uint[] df;
[MarshalAs(UnmanagedType.ByValArray, SizeConst=4)]
public uint[] dfn;
[MarshalAs(UnmanagedType.ByValArray, SizeConst=4)]
public IntPtr[] dc;
[MarshalAs(UnmanagedType.ByValArray, SizeConst=4)]
public float[] dg;
public float g;
public byte gs;
}
关键是这些数组以内联方式存储在struct中,因此必须使用进行编组UnmanagedType.ByValArray
。
函数声明应为:
[DllImport("DevControl.dll", CallingConvention=CallingConvention.Cdecl)]
static extern int DevConfig (ref A a, int b, uint c, bool[] d);
这确实假定final参数是数组,而不是指向单个布尔值的指针。只有你知道。另请注意调用约定。如所写,您的非托管函数为cdecl
。而且您确实需要在p / invoke中指定它。
现在,您将要面对的问题是struct中的2D数组dc
。处理该问题的唯一方法是手动分配和封送非托管内存。您不能使用,double[,]
因为那根本不会映射到double*[]
。因此,您需要IntPtr[]
然后使用Marshal
该类来完成工作。确切地说,如何解决所有问题是不可能的。它没有指定谁分配内存。
您在更新中声明要在C#中分配双精度数组以传递给非托管代码。一些示例代码:
IntPtr[] CreateUnmanagedArrays(double[][] arr)
{
IntPtr[] result = new IntPtr[arr.Length];
for (int i=0; i<arr.Length; i++)
{
result[i] = Marshal.AllocCoTaskMem(arr[i].Length*sizeof(double));
Marshal.Copy(arr[i], 0, result[i], arr[i].Length);
}
return result;
}
void DestroyUnmanagedArrays(IntPtr[] arr)
{
for (int i=0; i<arr.Length; i++)
{
Marshal.FreeCoTaskMem(arr[i]);
arr[i] = IntPtr.Zero;
}
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句