Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
Question
Wednesday, June 22, 2011 6:11 PM
I Searched, I cant find an exact answer.
I'm creating a C# wrapper dll (namespace and class) marshaling for a Delphi driver dll.
Constraints:
I cant use fixed keyword as I am tryin not to use any "unsafe" calls in my managed C# wrapper of a dll.
The dll cant be changed.
Basically I have a func that takes a pointer to an array of bytes. I can get this to work fine. However the practiclal way to do this for our customers is to allow then to create a struct with an array in it as is done in our C++ , C builder, Delphi, and VB 6.0 samples. My problem is having a fixed or variable length array inside a struct in C#. (without using "fixed")
I cant seem to get a constructor to do this either???
I could use a class instead of struct if i have to?
This is the C++ code equivelant I'm trying to emulate:
struct TUSBAI1616Config
{
byte ChannelRange[16];
byte CalibMode;
byte TrigMode;
byte StartStopCH;
byte Oversample;
};
This is then passed to the dll as a paameter by refference and is treated like an array of 20 bytes which works fine in C++.
ZeroMemory(&Config, sizeof(Config));
Config.CalibMode = 0; //Take actual data, not internal calibration sources.
Config.TrigMode = 5; //Scan selected channels each counter rising edge.
Config.Oversample = 0;//No oversample.
ConfigBufSize = sizeof(Config);
ADC_SetConfig (DeviceIndex, &Config, &ConfigBufSize);
Heres my latest C# code attempt, commented code didnt work:
public struct
{
public byte
public byte
public byte
public byte
public byte
public TUSBAI1616Config Config = new TUSBAI1616Config
public byte[] configArray = new byte
I cant get the array inside the struct to be a fixed lenght of 16 or dynamically set it with a constructor without errors??
Then heres an attempt to initialize the sstruct elements and copy/convert to an array and pass it to the dll.
This throws an exception because the array is still NULL. Also if anyone has a cleaner way to conver the struct to an array let me know. I'll work on that next, once I get the 16 byte sub array to work.
Config.CalibMode = 0;
Config.TrigMode = 5;
Config.Oversample = 0;
ConfigBufSize = 20;
for (int
for (int
AIOUSB.ADC_SetConfig(DeviceIndex, configArray, out ConfigBufSize);
Any suggestions would be greatly appreciated.
Can i make a 16 byte array a type then use it as a member of the struct?
Can a List help? Would a class allow me to do this? Collection?
I'll keep searching, reading, struggling, testing....
Thanks in advace :) Thanks, Richard
i = 0; i < 16; i++)
{
configArray[i] = Config.ChannelRange[i];
}
configArray[16] = Config.CalibMode;
configArray[17] = Config.TrigMode;
configArray[17] = Config.StartStopCH;
configArray[18] = Config.Oversample;
i = 0; i < 16; i++)
{
Config.ChannelRange[i] = 0; // exception!
}
// temp copy struct to array for dll call: ($$$Hack)
// sizeof(Config);
//No oversample.
//Scan selected channels each counter rising edge.
//Take actual data, not internal calibration sources.
[20];
// temp array for Config dll call:
//Config.ChannelRange = new byte[nDimension];
//int nDimension = 16;
();
//public TUSBAI1616Config Config;
Oversample;
}
StartStopCH;
TrigMode;
CalibMode;
[] ChannelRange;
//}
//ChannelRange = new ChannelRange[size];
//{
//TUSBAI1616Config(int size)
TUSBAI1616Config
// Struct for Config:
All replies (4)
Wednesday, June 22, 2011 9:01 PM ✅Answered | 1 vote
If the size 16 is fixed, then it's not a good choice for a parameter. If you want to create a fixed length byte declaraion in a struct you can do it this way:
public struct WithFixedLength
{
public readonly byte[] Data = new byte[16];
}
You will not be able to reassign the value of Data but you will be able to change the indices of the array.
If you want to convert a struct into a binary array, you need to use the Marshal class:
TUSBAI1616Config config;
int size = Marshal.SizeOf(config);
byte[] data = new byte[size];
IntPtr pointer = Marshal.AllocHGlobal(size);
Marshal.StructureToPtr(config, pointer , true);
Marshal.Copy(pointer, data , 0, size);
Marshal.FreeHGlobal(pointer);
Evan
Thursday, June 23, 2011 4:15 PM ✅Answered | 1 vote
To have the ChannelRange marshalled as an embedded array, you just need to apply a MarshalAs attribute.
Using a class instead of a struct allows the use of a default constructor. Note that a class is, by default, marshalled as a pointer to a struct. No need to pass it by reference.
public class TUSBAI1616Config
{
public TUSBAI1616Config()
{
ChannelRange = new byte [16];
CalibMode = 0;
TrigMode = 0;
StartStopCH = 0;
Oversample = 0;
}
[MarshalAs(UnmanagedType.ByValArray, SizeConst=16)]
public byte [] ChannelRange;
public byte CalibMode;
public byte TrigMode;
public byte StartStopCH;
public byte Oversample;
}
public TUSBAI1616Config Config = new TUSBAI1616Config();
Wednesday, June 22, 2011 7:00 PM
OK I'm learning reading MS Visual C# 2010 book on structs and arrays.
This is a corected version with contructor that takes size parameter and inits the array size:
Dang this editor sucks big time for pasted code, sorry.
// Struct for Config:
public struct TUSBAI1616Config
{
public TUSBAI1616Config(int size)
{
ChannelRange =
new byte [size];
CalibMode = 0;
TrigMode = 0;
StartStopCH = 0;
Oversample = 0;
}
public byte [] ChannelRange;
public byte CalibMode;
public byte TrigMode;
public byte StartStopCH;
public byte Oversample;
}
public TUSBAI1616Config Config = new TUSBAI1616Config(16);
This may work I'll try it. May want to use a class to then be able to overload the default contructor. Cant seem to pass the 16 in as a reference to an int variable though?
May also want to make the members private not public not sure on that yet.
Thanks, Richard
Friday, July 8, 2011 5:04 PM
Vin Jin Thanks for marking as answered.
Great replies. Thank you.
Yeh I ultimately pass an array of 21 bytes to the driver so these methods help keep the C# code clean and safe.
Cheers,
Richard
Thanks, Richard