Marshall array of structures - c#

I've spent a lot of time to look for the solution but still don't find it out.
I have 2 classes:
[StructLayout(LayoutKind.Sequential)]
public class Result
{
public int Number;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4)]
public string Name;
public int Size;
}
[StructLayout(LayoutKind.Sequential)]
public class CoverObject
{
public int NumOfResults;
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct, SizeConst = 4)]
public Result[] Results;
}
My expectation that the command Marshal.SizeOf(typeof(CoverObject)) will return 52, but not, it's just 20. Thus, all of marshall and unmarshall that I use later are not working.
Seeming it only counts the first member (Number) in Result class. Did I do anything wrong?

Change your classes to structs
[StructLayout(LayoutKind.Sequential)]
public struct Result
{
public int Number;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4)]
public string Name;
public int Size;
}
[StructLayout(LayoutKind.Sequential)]
public struct CoverObject
{
public int NumOfResults;
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct, SizeConst = 4)]
public Result[] Results;
}
some where else:
Marshal.SizeOf(typeof(CoverObject)) // it will return 52

Related

C# Convert an Ascii byte array to struct (i.e. with Marshal)

i have a byte array that is sent through sockets. The byte array is a ascii string.
var bytes = Encoding.ASCII.GetBytes("00000250Q+0000SPS_22MFR ");
How can i convert/marshal this byte array into a struct?
internal struct Header
{
public ulong Size;
public string Type;
public ushort Sequence;
public ushort ErrorCode;
public string Sender;
public string Receiver;
}
I already tried it with StructLayout and MarshalAs, but i get either an exception or a very different input/output.
[StructLayout(LayoutKind.Sequential, Size = 26, CharSet = CharSet.Ansi)]
internal struct SitTelegramHeader
{
public ulong Size;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 2)] public string Type;
public ushort Sequence;
public ushort ErrorCode;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 6)] public string Sender;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 6)] public string Receiver;
}
Is there any way to do this with Marshal/BinaryFormatter/etc. or do i have to convert it by hand?
Thx for help.

NVAPI problem return INCOMPATIBLE_STRUCT_VERSION

I am using NVAPI.dll to change gpu's core clock. using NvAPI_GPU_SetPstates20 function in nvapi.dll
The struct in C# for nvapi.dll is this:
[StructLayout(LayoutKind.Explicit, Pack = 8)]
internal struct dataStruct
{
[FieldOffset(0)]
public singleStruct single;
[FieldOffset(0)]
public rangeStruct range;
}
[StructLayout(LayoutKind.Sequential, Pack = 8)]
internal struct valuerange
{
public int min;
public int max;
}
[StructLayout(LayoutKind.Sequential, Pack = 8)]
internal struct NV_GPU_PSTATE20_BASE_VOLTAGE_ENTRY
{
public uint domainId;
public uint editable;//1
public uint reserved;//31
public uint voltageUV;
public NV_GPU_PERF_PSTATES20_PARAM_DELTA voltageDeltaUV;
}
[StructLayout(LayoutKind.Sequential, Pack = 8)]
internal struct NV_GPU_PERF_PSTATES20_PARAM_DELTA
{
public int value;
public valuerange valueRanges;
}
[StructLayout(LayoutKind.Sequential, Pack = 8)]
internal struct pstateStruct
{
public uint pStateId;
public uint editable;//1
public uint reserved;//31
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public NV_GPU_PSTATE20_CLOCK_ENTRY[]clocks;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public NV_GPU_PSTATE20_BASE_VOLTAGE_ENTRY[]baseVoltages;
}
[StructLayout(LayoutKind.Sequential, Pack = 8)]
internal struct singleStruct
{
public uint frequencyKHz;
}
[StructLayout(LayoutKind.Sequential, Pack = 8)]
internal struct rangeStruct
{
public uint minFrequencyKHz;
public uint maxFrequencyKHz;
public uint domainId;
public uint minVoltageUV;
public uint maxVoltageUV;
}
[StructLayout(LayoutKind.Sequential, Pack = 8)]
internal struct overVoltageStruct
{
public uint numVoltages;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public NV_GPU_PSTATE20_BASE_VOLTAGE_ENTRY []voltages;//[4]
}
[StructLayout(LayoutKind.Sequential, Pack = 8)]
internal struct NV_GPU_PSTATE20_CLOCK_ENTRY
{
public uint domainId;
public uint typeId;
public uint editable;//1
public uint reserved;//31
public NV_GPU_PERF_PSTATES20_PARAM_DELTA frequencyDeltaKHz;
public dataStruct data;
}
[StructLayout(LayoutKind.Sequential, Pack = 8)]
internal struct NV_GPU_PERF_PSTATES20_INFO
{
public uint version;
public uint editable;//1
public uint reserved;//31
public uint numPStates;
public uint numClocks;
public uint numBaseVoltages;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
public pstateStruct[] pStates;
public overVoltageStruct overVoltage;
}
This is my function:
public static void SetCoreClock(NvPhysicalGpuHandle handle,int clock)
{
NV_GPU_PERF_PSTATES20_INFO pStatesInfo=new NV_GPU_PERF_PSTATES20_INFO();
pStatesInfo.version = (uint) Marshal.SizeOf(typeof(NV_GPU_PERF_PSTATES20_INFO)) | 0x10000;
pStatesInfo.numPStates = 1;
pStatesInfo.numClocks = 1;
pStatesInfo.editable = 1;
pStatesInfo.reserved = 31;
pStatesInfo.pStates = new pstateStruct[16];
pStatesInfo.overVoltage.voltages = new NV_GPU_PSTATE20_BASE_VOLTAGE_ENTRY[4];
pStatesInfo.pStates[0].baseVoltages = new NV_GPU_PSTATE20_BASE_VOLTAGE_ENTRY[4];
pStatesInfo.pStates[0].clocks = new NV_GPU_PSTATE20_CLOCK_ENTRY[8];
pStatesInfo.pStates[0].clocks[0].editable = 1;
pStatesInfo.pStates[0].clocks[0].reserved = 31;
pStatesInfo.pStates[0].pStateId = 0;
pStatesInfo.pStates[0].clocks[0].domainId = 0;
pStatesInfo.pStates[0].clocks[0].typeId = 0;
pStatesInfo.pStates[0].clocks[0].frequencyDeltaKHz.value = clock;
pStatesInfo.pStates[0].clocks[0].frequencyDeltaKHz.valueRanges.max = 0;
pStatesInfo.pStates[0].clocks[0].frequencyDeltaKHz.valueRanges.min = 0;
a = NVAPI.NvAPI_GPU_SetPstates20(handle,ref pStatesInfo);
}
when I run the function "SetCoreClock". The value a return "INCOMPATIBLE_STRUCT_VERSION".
Is my struct wrong?
I found a C++ code. the code's struct is:
struct NV_GPU_PERF_PSTATES20_PARAM_DELTA
{
int value;
struct
{
int min;
int max;
} valueRange;
};
struct NV_GPU_PSTATE20_BASE_VOLTAGE_ENTRY
{
unsigned int domainId;
unsigned int editable : 1;
unsigned int reserved : 31;
unsigned int voltageUV;
NV_GPU_PERF_PSTATES20_PARAM_DELTA voltageDeltaUV;
};
struct NV_GPU_PSTATE20_CLOCK_ENTRY
{
unsigned int domainId;
unsigned int typeId;
unsigned int editable : 1;
unsigned int reserved : 31;
NV_GPU_PERF_PSTATES20_PARAM_DELTA frequencyDeltaKHz;
union
{
struct
{
unsigned int frequencyKHz;
} single;
struct
{
unsigned int minFrequencyKHz;
unsigned int maxFrequencyKHz;
unsigned int domainId;
unsigned int minVoltageUV;
unsigned int maxVoltageUV;
} range;
} data;
};
struct NV_GPU_PERF_PSTATES20_INFO
{
unsigned int version;
unsigned int editable : 1;
unsigned int reserved : 31;
unsigned int numPStates;
unsigned int numClocks;
unsigned int numBaseVoltages;
struct
{
unsigned int pStateId;
unsigned int editable : 1;
unsigned int reserved : 31;
NV_GPU_PSTATE20_CLOCK_ENTRY clocks[8];
NV_GPU_PSTATE20_BASE_VOLTAGE_ENTRY baseVoltages[4];
} pStates[16];
struct
{
unsigned int numVoltages;
NV_GPU_PSTATE20_BASE_VOLTAGE_ENTRY voltages[4];
} overVoltage;
};```
Thanks for helping me solved the problem.
it means you have the struct the incorrect size. a example I found said the version should be 0x11c94. things like reserved IMHO need to be removed. I had same issue and I did this to find the version:
uint GPUVER3 = (uint)Marshal.SizeOf(typeof(NV_GPU_PERF_PSTATES20_INFO_V1)) | 0x20000;
Once you get the version the same as 0x11c94 it should work.
C code I used to work this out
https://github.com/suppai/nvidia-overclock

Error in converting c++ union structure to c#

i have some complex structure in c++
typedef struct
{
long Length;
short Type;
union
{
MMTPConxReq ConxReq;
MMTPConxAck ConxAck;
MMTPConxNack ConxNack;
MMTPErrInd ErrInd;
MMTPDcnxReq DcnxReq;
MMTPDcnxAck DcnxAck;
MMTPDataMsg DataMsg;
MMTPSyncAck SyncAck;
MMTPStartReq StartReq;
MMTPStartAck StartAck;
MMTPStartNack StartNack;
MMTPSrvcMsg SrvcMsg;
MMTPDsptchMsg DsptchMsg;
MMTPRcnxReq RcnxReq;
} Data;
Ticks TimeStamp;
} MMTPMsg;
typedef struct
{
char SubsId[FIELD_SIZE_SUBS_ID+1];
int Level;
char Options[FIELD_SIZE_OPTIONS+1];
char AuthData[FIELD_SIZE_AUTH_DATA+1];
} MMTPConxReq;
// Contents of CONX-ACK message.
typedef struct
{
char Options[FIELD_SIZE_OPTIONS+1];
} MMTPConxAck;
// Contents of DATA-MSG message.
typedef struct
{
int SeqNb;
int DataSize;
MMTPAdminData AD;
char Data[FIELD_SIZE_DATA+1];
} MMTPDataMsg;
// Administrative data.
typedef struct
{
int Type;
int Size;
union
{
MMTPAdminDataA1 A1;
MMTPAdminDataA2 A2;
MMTPAdminDataE0 E0;
MMTPAdminDataE1 E1;
MMTPAdminDataG0 G0;
MMTPAdminDataM0 M0;
MMTPAdminDataRR RR;
MMTPAdminGeneric Generic;
} Data;
char Unknown[FIELD_SIZE_ADMIN];
} MMTPAdminData;
in conver to c# (step to step) i create this structs:
[StructLayout(LayoutKind.Sequential)]
internal struct MMTPMsg
{
public Int32 Length;
public MessageType Type;
//[MarshalAs(UnmanagedType.ByValArray, SizeConst = 10060)]
//public fixed byte Data[10060];
public MMTPMsgData Data;
public Int64 TimeStamp;
}
[StructLayout(LayoutKind.Explicit)]//,Size =10060)]
internal struct MMTPMsgData
{
[FieldOffset(0)]
public MMTPConxReq ConxReq;//12+4+17+9
[FieldOffset(0)]
public MMTPConxAck ConxAck;//17
//[FieldOffset(0)]
//public MMTPConxNack ConxNack;//e
//[FieldOffset(0)]
//public MMTPErrInd ErrInd;//e+4+4+4+(9500+256+24+1)
//[FieldOffset(0)]
//public MMTPDcnxReq DcnxReq;//e+4
//[FieldOffset(0)]
//public MMTPDcnxAck DcnxAck;//4
[FieldOffset(0)]
public MMTPDataMsg DataMsg;//4+4+(4+4+()+256)+9501
//[FieldOffset(0)]
//public MMTPSyncAck SyncAck;
//[FieldOffset(0)]
//public MMTPStartReq StartReq;
[FieldOffset(0)]
public MMTPStartAck StartAck;
//[FieldOffset(0)]
//public MMTPStartNack StartNack;
//[FieldOffset(0)]
//public MMTPSrvcMsg SrvcMsg;
//[FieldOffset(0)]
//public MMTPDsptchMsg DsptchMsg;
//[FieldOffset(0)]
//public MMTPRcnxReq RcnxReq;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]//, CharSet = CharSet.Ansi)]
unsafe internal struct MMTPConxReq
{
public fixed byte SubsId[Constants.FIELD_SIZE_SUBS_ID + 1];
public int Level;
public fixed byte Options[Constants.FIELD_SIZE_OPTIONS + 1];
public fixed byte AuthData[Constants.FIELD_SIZE_AUTH_DATA + 1];
}
internal struct MMTPConxAck
{
//[MarshalAs(UnmanagedType.ByValTStr, SizeConst = Constants.FIELD_SIZE_OPTIONS + 1)]
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = Constants.FIELD_SIZE_OPTIONS + 1)]
public string Options;//[Constants.FIELD_SIZE_OPTIONS + 1];
}
internal struct MMTPDataMsg
{
public int SeqNb;
public int DataSize;
public MMTPAdminData AD;
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = Constants.FIELD_SIZE_DATA + 1)]
public byte[] Data;
}
when run the c# app, i get this error
System.TypeLoadException: 'Could not load type 'TestSle.MMTPMsgData' from assembly 'TestSle, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' because it contains an object field at offset 0 that is incorrectly aligned or overlapped by a non-object field.'
if i comment
this line from MMTPMsgData struct:
[FieldOffset(0)]
public MMTPConxReq ConxReq;//12+4+17+9
no error happen but i need this data.
what is wrong
i can not understand problem
help me please

How to marshal wchar[]

I've found plenty of information about how to marshal wchar_t and wchar* on the internet, but right now I am trying to marshal the WINBIO_STRING type, which is defined as wchar[256]. Marshalling it as an array of char[] works, but then every other element in the array is \0, and I would like to avoid this. Is there a more proper way to marshal this data (which is a member of a struct, the WINBIO_UNIT_SCHEMA struct in particular). This is my code:
[StructLayout(LayoutKind.Sequential)]
public struct BiometricUnitSchema
{
public int UnitId;
public BiometricPoolType PoolType;
public BiometricType BiometricFactor;
public BiometricSubtype SensorSubType;
public BiometricCapabilities Capabilities;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
public char[] DeviceInstanceId;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
public char[] Description;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
public char[] Manufacturer;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
public char[] Model;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
public char[] SerialNumber;
public BiometricVersion FirmwareVersion;
}
I also have the problem of the FirmwareVersion field always containing MajorVersion and MinorVersion values of 0, but I am not sure if this result is incorrect or simply misleading.
I fixed this problem by marshaling WINBIO_STRING as a string in C# instead of a char[]. I also had to add a Unicode charset to my structure.
My new structure:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct BiometricUnitSchema
{
public int UnitId;
public BiometricPoolType PoolType;
public BiometricType BiometricFactor;
public BiometricSubtype SensorSubType;
public BiometricCapabilities Capabilities;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string DeviceInstanceId;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string Description;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string Manufacturer;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string Model;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string SerialNumber;
public BiometricVersion FirmwareVersion;
}

Another PInvoke - error message says source not found?

The struct that i have built in c# when run against the function does not give me one of the error message that tell me something is wrong with the struct. It says that a source file could not be found. Again, I don't know much about this DLL b/c of lack of documentation. But I am still thinking it is because I set the struct up wrong. Most likely i'm thinking the 3rd struct where it is referencing a struct within the struct.
i was hoping for some feedback on the work I did.
Thanks for the assistance.
This is what was provided in C:
int BatchTotal_Transactions(int transType, pTGiftCardReqBatchTotal req, pTGiftCardRespBatchTotal resp, int (*Com)(char *));
typedef struct _tagGiftCardReqBatchTotal
{
char Password[9];
char OperatorID[9];
char BatchNum[14];
char StartDate[11];
char EndDate[11];
unsigned char Type;
} TGiftCardReqBatchTotal, *pTGiftCardReqBatchTotal;
typedef struct _tagGiftCardRespBatchTotal
{
char Result;
char TerminalId[17];
unsigned char DispMsgControl;
char DispMsg[256];
char Display[41];
char Date[11];
char Time[9];
char RespCode[4];
char BatchNum[14];
char ErrorFlag;
char CustLang;
char UserLang;
char OpenDate[17];
char ClosedDate[17];
char StartDate[11];
char EndDate[11];
char BatchStatus;
int CardTypeNum;
TGiftCardTotals GctHost[MAX_CARD_CODES];
TGiftCardTotals GctTRS[MAX_CARD_CODES];
} TGiftCardRespBatchTotal, *pTGiftCardRespBatchTotal;
typedef struct _tagGiftCardTotals
{
unsigned short CardCode;
unsigned short PurchaseNum;
long PurchaseTotal;
unsigned short RefundNum;
long RefundTotal;
unsigned short RedemptionNum;
long RedemptionTotal;
unsigned short CorrectionNum;
long CorrectionTotal;
long PurchaseBenefitTotal;
long RefundBenefitTotal;
long RedemptionBenefitTotal;
} TGiftCardTotals, *pTGiftCardTotals;
And this is how I did it in C#:
[DllImport("batch.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Auto)]
public static extern int BatchTotal_Transactions(int transType, ref giftCardReqBatchTotal req, ref giftCardRespBatchTotal resp, IntPtr com);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct _tagGiftCardReqBatchTotal
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 9)]
public string Password;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 9)]
public string OperatorID;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
public string BatchNum;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 11)]
public string StartDate;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 11)]
public string EndDate;
public byte Type;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct _tagGiftCardRespBatchTotal
{
public byte Result;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 17)]
public string TerminalId;
public byte DispMsgControl;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string DispMsg;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 41)]
public string Display;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 11)]
public string Date;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 9)]
public string Time;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4)]
public string RespCode;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
public string BatchNum;
public byte ErrorFlag;
public byte CustLang;
public byte UserLang;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 17)]
public string OpenDate;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 17)]
public string ClosedDate;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 11)]
public string StartDate;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 11)]
public string EndDate;
public byte BatchStatus;
int CardTypeNum;
[MarshalAs(UnmanagedType.Struct, SizeConst = 1024)]
public _tagGiftCardTotals GctHost;
[MarshalAs(UnmanagedType.Struct, SizeConst = 1024)]
public _tagGiftCardTotals GctTRS;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct _tagGiftCardTotals
{
public UInt16 CardCode;
public UInt16 PurchaseNum;
public int PurchaseTotal;
public UInt16 RefundNum;
public int RefundTotal;
public UInt16 RedemptionNum;
public int RedemptionTotal;
public UInt16 CorrectionNum;
public int CorrectionTotal;
public int PurchaseBenefitTotal;
public int RefundBenefitTotal;
public int RedemptionBenefitTotal;
}
Are you sure the error isn't the following:
Specified module could not be found.
If this is the error then it is because the dll could not be found. Make sure the dll is in your path:
http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.dllimportattribute.value.aspx

Categories