在理解编组C ++ DLL时似乎还有另一个问题。
这是C ++函数的def和& struct:
#define SIZE_PLATE (28l)
#define SIZE_HJT (15l)
#define SIZE_DATE (10)
typedef struct _tyrfdePlate
{
TCharA PlateID[SIZE_PLATE];
TInt32 NetworkID;
TInt32 CityID;
TCharA DateS[SIZE_DATE];
TCharA DateE[SIZE_DATE];
TInt32 Width;
TInt32 Height;
TBool Light;
TBool Roll;
TCharA CycleID[4];
TInt16 OrHjt1;
TCharA HJTID1[SIZE_HJT];
TInt16 OrHjt2;
TCharA HJTID2[SIZE_HJT];
TInt16 OrHjt3;
TCharA HJTID3[SIZE_HJT];
TInt16 OrHjt4;
TCharA HJTID4[SIZE_HJT];
} tyrfdePlate;
TInt32 __stdcall tyrfdeSetResults(TInt32 TargetNbr, const TInt32* pTargets, TInt32 PlateNbr, const tyrfdePlate* pPlates);
这是我根据之前提出的问题在C#中所做的:
[StructLayout(LayoutKind.Sequential, Size = 138), Serializable]
public struct Plate
{
[MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 28)]
public string PlateID;
public int NetworkID;
public int CityID;
[MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 10)]
public string DateS;
[MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 10)]
public string DateE;
public int Width;
public int Height;
public bool Light;
public bool Roll;
[MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 4)]
public string CycleID;
public short OrHJT1;
[MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 15)]
public string HJTID1;
public short OrHJT2;
[MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 15)]
public string HJTID2;
public short OrHJT3;
[MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 15)]
public string HJTID3;
public short OrHJT4;
[MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 15)]
public string HJTID4;
}
[DllImport("tyrfde.dll", EntryPoint = "tyrfdeSetResults")]
public static extern int SetResults(int targetNbr, [MarshalAs(UnmanagedType.LPArray)] int[] targetIds, int plateNbr, [MarshalAs(UnmanagedType.LPArray)] Plate[] plates);
这是一个电话示例:
List<Plate> plates = new List<Plate>();
plates.Add(new Plate() { PlateID = "56013208", NetworkID = 992038, CityID = 60010, DateS = "01012009", DateE = "31122010", Width = 400, Height = 300, Light = false, Roll = false, CycleID = "0", OrHJT1 = 2, HJTID1 = "579026356", OrHJT2 = 2, HJTID2 = "579026377", OrHJT3 = 2, HJTID3 = "58571903", OrHJT4 = 0, HJTID4 = "0" });
int[] targets = new int[]{1,2,11,12,130};
int result = SetResults(5, targets, 1, plates.ToArray());
请注意,我也尝试使用原生Array而不是通用列表,结果相同。
所以基本上我正在使用相同的数据重做用C ++制作的测试应用程序。不幸的是,函数返回-1,这意味着发生了错误,但C ++应用程序返回23.所以我猜测我的struct和/或我传递的参数有问题。可能是int []。我试图让ref的默认编组,但没有工作。有什么想法吗?
修改
由于类型定义似乎非常重要,因此def:
typedef void TVoid;
typedef bool TBool;
typedef char TCharA; // character 8
typedef TCharA TChar; // character 8
typedef wchar_t TCharW; // character 16
typedef signed char TInt08; // integer signed 8
typedef unsigned char TUnt08; // integer unsigned 8
typedef signed short TInt16; // integer signed 16
typedef unsigned short TUnt16; // integer unsigned 16
typedef signed long TInt32; // integer signed 32
typedef unsigned long TUnt32; // integer unsigned 32
typedef float TFlt32; // float 32
typedef double TFlt64; // float 64
答案 0 :(得分:1)
你真正想要的是一种调试方法。最简单的方法是编写自己的dll,使用这种数据类型,看看另一方面结构会发生什么。
我怀疑你的真正问题是结构调整以及它是如何运作的。我在你的代码中看到的是一堆奇数大小的元素(15,28,10)。有可能是目标系统已经消失并且在至少2个字节(如果不是4个字节边界)上对齐结构元素。你不应该检查。
您还可以通过编写消耗实际结构的C并在结构元素上输出一堆offsetof()调用的结果来节省一些时间。
你的方法应该是有条不紊的,而不是霰弹枪,方法的一部分是测量和反馈。这将给你们两个。
答案 1 :(得分:1)
您在[StructLayout]属性中提供的Size属性是一个很好的提示。使用此代码段验证:
int len = Marshal.SizeOf(typeof(Plate));
System.Diagnostics.Debug.Assert(len == 138);
你要通过这个断言的唯一方法是用“byte”替换“bool”(所以TBool = 1个字节)并使用1的打包:
[StructLayout(LayoutKind.Sequential, Pack=1), Serializable]
public struct Plate {
//...
}
如果仍然无效,那么你真的必须调试非托管代码。
答案 2 :(得分:0)
1)TBool有多少字节? 1? 4?
2)您可以删除StructLayout(LayoutKind.Sequential,Size = 138)属性,因为默认情况下它是Sequential,并且Size可以由运行时确定。
3)您可以删除[MarshalAs(UnmanagedType.LPArray)]属性。 marshaller知道如何编组数组,但请注意,默认情况下,数组被编组为[IN],因此如果c ++代码要编辑数组的内容,则需要使用[IN,OUT]属性。
答案 3 :(得分:0)
dll中的const TInt32* pTargets
参数怎么样?我不知道它是如何使用的,但这表明指向单个TInt32实例的指针,而不是TInt32的数组。当然,这取决于它在代码中的使用方式。