P / Вызвать параметр сортировки задачи - PullRequest
1 голос
/ 03 декабря 2009

Кажется, у меня есть еще одна проблема в понимании сортировки в C ++ DLL.

Вот определение функции и структуры C ++:

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

Обратите внимание, что я также пытался использовать нативный массив вместо общего списка с тем же результатом.

Так что, в основном, я переделываю тестовое приложение, созданное на C ++ с теми же данными. К сожалению, функция возвращает мне -1, что означает, что произошла ошибка, но приложение C ++ возвращает 23. Поэтому я догадался, что что-то не так с моей структурой и / или параметром, который я передаю. Вероятно, int []. Я попытался позволить маршалу по умолчанию с ref, но не сработало. Есть идеи?

EDIT

Поскольку определение типа представляется очень важным, вот определение:

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 ]

1 голос
/ 03 декабря 2009

Атрибут Size, который вы указали в атрибуте [StructLayout], является хорошей подсказкой. Проверьте это с помощью этого фрагмента:

        int len = Marshal.SizeOf(typeof(Plate));
        System.Diagnostics.Debug.Assert(len == 138);

Единственный способ получить это утверждение - заменить "bool" на "byte" (т.е. TBool = 1 байт) и использовать упаковку 1:

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

Если это по-прежнему не работает, вам действительно придется отлаживать неуправляемый код.

1 голос
/ 03 декабря 2009

То, что вы действительно хотите, это способ отладки этого. Самый простой способ - написать свою собственную dll, которая использует этот тип данных, и посмотреть, что происходит со структурой на другой стороне.

Я подозреваю, что ваша настоящая проблема - выравнивание структуры и как это работает. То, что я вижу в вашем коде, это набор элементов с нечетными размерами (15, 28, 10). Скорее всего, целевая система прошла и выровняла элементы структуры по крайней мере на 2 байта, если не на 4 байтовых границах. Тем не менее, вы должны проверить.

Вы также можете сэкономить некоторое время, написав C, который потребляет фактическую структуру и выводит результаты набора offsetof () вызовов для элементов структуры.

Вы должны быть методичным в своем подходе вместо дробовика, и частью методологии является измерение и обратная связь. Это даст вам обоим.

0 голосов
/ 03 декабря 2009

Как насчет аргумента const TInt32* pTargets в dll. Я не знаю, как он используется, но это предполагает указатель на один экземпляр TInt32, а не массив TInt32. Конечно, это зависит от того, как он используется в коде.

0 голосов
/ 03 декабря 2009

1) Сколько байтов составляет TBool? 1? 4

2) Вы можете удалить атрибут StructLayout (LayoutKind.Sequential, Size = 138), поскольку по умолчанию он является последовательным, а размер может определяться средой выполнения.

3) Вы можете удалить атрибут [MarshalAs (UnmanagedType.LPArray)]. Маршаллер знает, как маршировать массивы, но обратите внимание, что по умолчанию массивы маршалируются как [IN], поэтому, если код c ++ собирается редактировать содержимое массивов, вам нужно использовать атрибут [IN, OUT]. *

...