Маршал C структура в C# - PullRequest
       75

Маршал C структура в C#

2 голосов
/ 29 марта 2020

Я пытаюсь вызвать функцию в C, которая имеет следующую подпись от C#

typedef struct _wfs_result 
{
   ULONG RequestID;
   USHORT hService;
   TIMESTAMP tsTimestamp;
   LONG hResult;
   union {
      DWORD dwCommandCode;
      DWORD dwEventID;
   } u;
   LPVOID lpBuffer;
} WFSRESULT, *LPWFSRESULT;

LONG WFSGetInfo(USHORT hService, DWORD dwCategory, LPVOID lpQueryDetails, DWORD dwTimeOut, LPWFSRESULT *lppResult)

typedef struct _wfs_pin_status
{
   WORD fwDevice;
   WORD fwEncStat;
   LPSTR lpszExtra;
   DWORD dwGuidLights[WFS_PIN_GUIDLIGHTS_SIZE];
   WORD fwAutoBeepMode;
   DWORD dwCertificateState;
   WORD wDevicePosition;
   USHORT usPowerSaveRecoveryTime;
} WFSPINSTATUS, *LPWFSPINSTATUS;

и мой код C# выглядит следующим образом:

[DllImport("msxfs")]
public static extern int WFSGetInfo(ushort hService, uint dwCategory, IntPtr lpQueryDetails, uint dwTimeOut, ref WFSRESULT lppResult);

[StructLayout(LayoutKind.Explicit)]
public struct WFSRESULT
{
   [FieldOffset(0)]
   public uint RequestID;
   [FieldOffset(4)]
   public ushort hService;
   [FieldOffset(6)]
   public SYSTEMTIME tsTimestamp;
   [FieldOffset(22)]
   public int hResult;
   [FieldOffset(26)]
   public uint dwCommandCode;
   [FieldOffset(26)]
   public uint dwEventID;
   [FieldOffset(30)]
   public IntPtr lpBuffer; //It should be pointer to a structure that contain more information
}

[StructLayout(LayoutKind.Sequential)]
public struct SYSTEMTIME
{
   public ushort wYear;
   public ushort wMonth;
   public ushort wDayOfWeek;
   public ushort wDay;
   public ushort wHour;
   public ushort wMinute;
   public ushort wSecond;
   public ushort wMilliseconds;
}

[StructLayout(LayoutKind.Sequential)]
public struct WFSPINSTATUS
{
   public ushort fwDevice;
   public ushort fwEncStat;
   public string lpszExtra;
   [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
   public uint[] dwGuidLights;
   public ushort fwAutoBeepMode;
   public uint dwCertificateState;
   public ushort wDevicePosition;
   public ushort usPowerSaveRecoveryTime;
}

private void WfsGetInfo()
{
   WFSRESULT wfsRESULT = new WFSRESULT();

   int hResult = WFSGetInfo(_lphService, InfoCommands.WFS_INF_PIN_CAPABILITIES, IntPtr.Zero, WFS_INDEFINITE_WAIT, ref wfsRESULT);

   WFSPINSTATUS pinStatus = Marshal.PtrToStructure<WFSPINSTATUS>(wfsRESULT.lpBuffer);
}

Моя проблема в том, что всякий раз, когда я вызываю функцию WFSGetInfo, она будет выполнена успешно (hResult == 0), но будут заполнены только RequestID в wfsRESULT, а все остальные значения будут равны 0 (значение по умолчанию), и при попытке преобразовать lpBuffer в WFSPINSTATUS следующее исключение произошло. System.NullReferenceException: 'Object reference not set to an instance of an object.'

Не думаю, что проблема в вызываемой dll msxfs, потому что это стандартная windows dll.

Я пробую много решений и техник (например, Я пытаюсь установить SYSTEMTIME layout на Explicit), но с тем же результатом; Я не буду добавлять свои испытания, чтобы сократить код.

Я провел большой поиск относительно структуры маршалинга и объединения в C, и следующий сайт был очень полезен Маршалинг с C#

Я не уверен, что эта информация полезна, но я строю интеграцию CEN/XFS с устройством EPP.

...