Я пытаюсь вызвать функцию в 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
т.к. это стандартная dll windows.
Я пробую много решений и методов (например, я пытаюсь установить макет SYSTEMTIME
на Explicit
), но с тем же результатом; Я не буду добавлять свои испытания, чтобы сократить код.
Я провел много поисков относительно структуры маршалинга и объединения в C
, и следующий сайт оказался очень полезным Маршалинг с C#
Я не уверен, что эта информация полезна, но я создаю CEN/XFS
интеграцию с устройством EPP.
lpBuffer
равно0x00000000
. и, как указано в документации, возвращаемый функцией результат должен быть возвращен вhResult
. Я пытаюсь установить его значение равным 100, чтобы убедиться, что оно не является значением по умолчанию, прежде чем отправлять его, и когда оно вернулось, его значение все еще было 100. - person Ebraheem   schedule 29.03.2020WFSGetInfo
, вам нужно определитьlppResult
следующим образом:LPWFSRESULT lpResult = NULL;
, и передать адрес указателя функции:WFSGetInfo(...., &lpResult)
. XFS выделит вам память. После того, как вы используете эту информацию, вам нужно освободить этотlpResult
. - person SuperG280   schedule 30.03.2020