C# P/Invoke问题编组参数 P.>在对C++ DLL进行编组理解方面,我似乎还有一个问题。 这里是C++函数的DEF和结构: #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# P/Invoke问题编组参数 P.>在对C++ DLL进行编组理解方面,我似乎还有一个问题。 这里是C++函数的DEF和结构: #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#,pinvoke,marshalling,C#,Pinvoke,Marshalling,这是我在C#中根据我之前提出的一个问题所做的: [StructLayout(LayoutKind.Sequential, Size = 138), Serializable] public struct Plate { [MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 28)] public string PlateID; public int NetworkID; public int CityID

这是我在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());
1) 一个TBool有多少字节?1.四?

2) 您可以删除StructLayout(LayoutKind.Sequential,Size=138)属性,因为默认情况下它是连续的,并且大小可以由运行时确定


3) 您可以删除[Marshallas(UnmanagedType.LPArray)]属性。封送器知道如何排列数组,但是注意,默认数组按[in ]排列,因此如果C++代码将编辑数组的内容,则需要使用[in,Out]属性。

在DLL中的<代码> const TtIt32 *pObjult< /Cord>参数如何。我不知道它是如何使用的,但这意味着指向单个TInt32实例的指针,而不是TInt32的数组。当然,这取决于它在代码中的使用方式。

您真正想要的是一种调试方法。最简单的方法是编写使用此数据类型的dll,并查看另一端的结构会发生什么情况

我怀疑你真正的问题是结构调整以及如何进行。我在代码中看到的是一堆大小奇数的元素(15、28、10)。目标系统很可能已经在至少2字节(如果不是4字节)的边界上对齐了结构元素。当然你应该检查一下

您还可以通过编写使用实际结构并输出对结构元素的一系列调用结果的C来节省一些时间


你应该有条不紊地使用你的方法而不是散弹枪,方法的一部分是进行测量和反馈。这将为您提供这两个属性。

您在[StructLayout]属性中提供的大小属性是一个很好的提示。验证是否使用此代码段:

        int len = Marshal.SizeOf(typeof(Plate));
        System.Diagnostics.Debug.Assert(len == 138);
通过此断言的唯一方法是将“bool”替换为“byte”(因此TBool=1 byte),并使用1:

[StructLayout(LayoutKind.Sequential, Pack=1), Serializable]
public struct Plate {
  //...
}

如果仍然不起作用,那么您将不得不调试非托管代码。

您是否尝试过这些工具:或者?从未尝试过这些工具,将立即对其进行调查。第一个工具不允许您打开自定义dll和自定义头文件。第二个是自动生成dll,不显示生成的实际代码。不错的工具,但与我的问题无关。1)1)2)OK 3)UnmanagedType.LPArray是昨天添加的,用于修复CLR在结构上引发的异常。int[]可能不成功,但删除它并不能解决问题。1)引发的CLR异常是什么?2) 将Light和Roll的类型从bool更改为byte。1)2)完成,但未修复我尝试将两个结构[Out]放回原样,int[]返回原样,但板[]返回空对象,而调用前所有对象都已正确填充。这说明DllImport上的Plate结构存在错误。1)是否将DllImport.CallingConvention设置为StdCall?2) 什么是TCharA?2字节?1字节?3) 这个库希望资料采用什么编码?ascii码?unicode?4) 出于调试目的,将字符串字段的类型更改为固定字符[]字段或固定字节[]字段,具体取决于TChar是什么。是l,不是1。28长。比较结果是144而不是138,因此布尔值被编组为4,而不是第一个答案所建议的1。Pack=1也是必需的,否则它会崩溃这是决定性的要点,因为我已经测试了字节而不是bool。因为Pack=1是我的主要问题,所以我将此标记为答案。
[StructLayout(LayoutKind.Sequential, Pack=1), Serializable]
public struct Plate {
  //...
}