代码之家  ›  专栏  ›  技术社区  ›  baptiste

P/Invoke问题编组参数

  •  1
  • baptiste  · 技术社区  · 16 年前

    这里是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);
    

    [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());
    

    注意,我还尝试使用本机数组而不是通用列表,结果相同。

    所以基本上我正在重做用相同数据制作的C++应用程序。不幸的是,函数返回ME 1,这意味着发生了错误,但是C++应用程序返回23。所以我猜到我的结构和/或参数的错误。可能是int[]。我尝试让默认封送处理使用ref,但没有成功。有什么想法吗?

    编辑

    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
    
    4 回复  |  直到 16 年前
        1
  •  1
  •   Hans Passant    16 年前

            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 {
      //...
    }
    

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

        2
  •  1
  •   plinth    16 年前

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

    offsetof() 对struct元素的调用。

        3
  •  0
  •   Hasani Blackwell    16 年前

    1) 一个TBool有多少字节?1.4.

        4
  •  0
  •   scottm    16 年前

    这个怎么样 const TInt32* pTargets dll中的参数。我不知道它是如何使用的,但这意味着指向单个TInt32实例的指针,而不是TInt32的数组。当然,这取决于它在代码中的使用方式。