在VC++中结构定义:
typedef struct
{
int nDataNum; // 数据个数
double *pdData; // 存放数据数组
} PDData;在VC++中函数定义:
int Test(..., PDData *pOutputData, ...) {}在C#中相应结构定义:
[StructLayout(LayoutKind.Sequential)]
public class PDData
{
public int nDataNum; public double[] pdData; public PDData(double[] pdData)
{
this.pdData = pdData;
this.nDataNum = pdData.Length;
}
}在C#中外部方法定义:
[DllImport("TestDll.dll")]
public static extern int PredictData(
...,
[MarshalAs(UnmanagedType.LPStruct)]
PDData pOutputData,
...);
在C#中调用该方法:(MAX_OUTPUT_DATA_NUM为常量)
PDData pOutputData = new PDData(new double[MAX_OUTPUT_DATA_NUM]);
Test(..., pOutputData, ...);在VC++中对该Dll进行测试完全正确,pdData数组中都有值输出,但在C#中按上面的方法调用该Dll时也可以正常运行,也可以得到函数返回值,但pdData数组中没有值输出。我还尝试以下几种方法:
在C#中将PDData定义成struct,并定义外部方法将pOutputData参数定义成ref;
在C#中定义外部方法将pOutputData参数定义成ref;
在C#中定义结构时将double[] pdData标识为[MarshalAs(UnmanagedType.SafeArray, SafeArraySubType=VarEnum.VT_R8)];
在C#中定义结构时将double[] pdData标识为[MarshalAs(UnmanagedType.ByValArray, SizeConst=MAX_OUTPUT_DATA_NUM, ArraySubType=UnmanagedType.R8)];
在C#中定义结构时将double[] pdData标识为[MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.R8, SizeConst=MAX_OUTPUT_DATA_NUM)];
...但这些方法运行时都是出错,不是报内存不足就是报未将对象引用到实例,无比郁闷,请大家帮忙看看是什么地方出的问题,为什么结构中的数组的值传不回来?或者大家帮忙找个C#中调用非托管Dll中的带有返回对象参数的例子,谢谢
typedef struct
{
int nDataNum; // 数据个数
double *pdData; // 存放数据数组
} PDData;在VC++中函数定义:
int Test(..., PDData *pOutputData, ...) {}在C#中相应结构定义:
[StructLayout(LayoutKind.Sequential)]
public class PDData
{
public int nDataNum; public double[] pdData; public PDData(double[] pdData)
{
this.pdData = pdData;
this.nDataNum = pdData.Length;
}
}在C#中外部方法定义:
[DllImport("TestDll.dll")]
public static extern int PredictData(
...,
[MarshalAs(UnmanagedType.LPStruct)]
PDData pOutputData,
...);
在C#中调用该方法:(MAX_OUTPUT_DATA_NUM为常量)
PDData pOutputData = new PDData(new double[MAX_OUTPUT_DATA_NUM]);
Test(..., pOutputData, ...);在VC++中对该Dll进行测试完全正确,pdData数组中都有值输出,但在C#中按上面的方法调用该Dll时也可以正常运行,也可以得到函数返回值,但pdData数组中没有值输出。我还尝试以下几种方法:
在C#中将PDData定义成struct,并定义外部方法将pOutputData参数定义成ref;
在C#中定义外部方法将pOutputData参数定义成ref;
在C#中定义结构时将double[] pdData标识为[MarshalAs(UnmanagedType.SafeArray, SafeArraySubType=VarEnum.VT_R8)];
在C#中定义结构时将double[] pdData标识为[MarshalAs(UnmanagedType.ByValArray, SizeConst=MAX_OUTPUT_DATA_NUM, ArraySubType=UnmanagedType.R8)];
在C#中定义结构时将double[] pdData标识为[MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.R8, SizeConst=MAX_OUTPUT_DATA_NUM)];
...但这些方法运行时都是出错,不是报内存不足就是报未将对象引用到实例,无比郁闷,请大家帮忙看看是什么地方出的问题,为什么结构中的数组的值传不回来?或者大家帮忙找个C#中调用非托管Dll中的带有返回对象参数的例子,谢谢
{
int nDataNum; // 数据个数
double *pdData; // 存放数据数组
} PDData;这里有问题吧?PDData不是指针,怎么以P开头了?有歧义 :-)
还有在struct里面定义的数组,最好是定长的,比如double pdData[10]在C#里面你可以这样定义等价的结构:
struct DData
{
public int nDataNum;
public IntPtr pdData;
}然后使用Marshal.Copy方法把数据从指针复制到本地数组
typedef struct
{
int nDataNum; // 数据个数
double pdData[10]; // 存放数据数组
} PDData;C#里面这样对应:
[StructLayout(LayoutKind.Sequential)]
struct DData
{
public int nDataNum;
[MarshalAs(UnmanagedType.ByValArray, SizeConst=10)]
public double[] pdData;
}
// marshal_embedded_pointer.cpp
// compile with: /clr
#include <iostream>using namespace System;
using namespace System::Runtime::InteropServices;
using namespace stdcli::language;// unmanaged struct, but visible to both
struct ListStruct
{
int count;
double* item;
};
#pragma unmanagedvoid UnmanagedTakesListStruct(ListStruct list)
{
printf("[unmanaged] count = %d\n", list.count);
for (int i=0; i<list.count; i++)
{
printf("array[%d] = %f\n", i, list.item[i]);
}}#pragma managedint main()
{
ListStruct list;
list.count = 10;
list.item = new double[list.count];Console::WriteLine("[managed] count = {0}", list.count);
Random^ r = gcnew Random();
for (int i=0; i<list.count; i++)
{
list.item[i] = r->NextDouble() * 100.0;
Console::WriteLine("array[{0}] = {1}", i, list.item[i]);
}UnmanagedTakesListStruct( list );
delete list.item;return 0;
}在托管里面给pdData赋初值的时候应该用pin指针钉住托管堆上的数据或者在传统堆上分配数据。
参考http://msdn2.microsoft.com/library/23acw07k.aspx