The MSDN document that I am trying to follow is located here. Basically I am trying to figure out in C# how to read that pointer into a list of the DHCP_OPTION_DATA structures.
I have the following code but I don't think that it is the proper way to do this.
DHCP_OPTION_ARRAY optionArray = (DHCP_OPTION_ARRAY)Marshal.PtrToStructure(options, typeof(DHCP_OPTION_ARRAY));
List<DHCP_OPTION> allOptions = new List<DHCP_OPTION>();
for (int i = 0; i < optionArray.NumElements; i++) {
DHCP_OPTION option = (DHCP_OPTION)Marshal.PtrToStructure(optionArray.Options, typeof(DHCP_OPTION));
allOptions.Add(option);
optionArray.Options = (IntPtr)((int)optionArray.Options + (int)Marshal.SizeOf(option));
}
Since I can't Marshal the pointer into a generic list collection I tried this way. My problem is that I am getting skewed results based on how much I increase the IntPtr to. Initially I was doing this.
optionArray.Options = (IntPtr)((int)optionArray.Options + (int)Marshal.SizeOf(typeof(DHCP_OPTION_DATA)));
However, I then realized that the next element would be located after the size of the actual option.
So the question still remains, how do I Marshal a Ptr to a list of structures?
EDIT 1
I posted the wrong article it is fixed now.
EDIT 2
Although both answers were great, I chose the answer to my problem because it addressed my lack of understanding of how the data was being handled on the back end of marshaling the information.
Is the first option object you get correct?
If so, the reason for the rest being skewed most likely is the alignment of the structure.
You could try to find the correct alignment, for example:
var offset = (int)Marshal.SizeOf(typeof(DHCP_OPTION_DATA));
var alignment = 4;
var remainder = offset % alignment;
if(remainder != 0)
offset += alignment - remainder;
optionArray.Options = (IntPtr)((int)optionArray.Options + offset);
Here is a paper Jason Rupard wrote using the DHCP_OPTION_ARRAY...
http://www.rupj.net/portfolio/docs/dws-writeup.pdf
Looks like he has everything you need and more... :)
Although looking at it you could define the structure a little differently and have it automatically turned into an array upon deserialization if you get the Pack attribute right.
Related
I am not very experienced in C#, but have lots of experience from other languages.
I am doing a project in C# where I have to read and modify large files.
For this I have coded a buffering scheme where I keep chunks of data in memory, and swap them to disk when I need to read more. I always eliminate the [0] element from the array, by moving the following elements back one position.
public struct TBBuffer
{
public long offset;
public short[] data;
public GCHandle dataHandle;
}
//tb is a TBBuffer[], the data[] is initialized to 4096.
If I use a small sample file, where everything fits in the buffers allocated, everything works as intended.
Whenever I need to free up some memory for more data I do:
int bufIdx,bufNo;
for (bufIdx = 0; bufIdx < tb.buffer.Length - 1; bufIdx++)
{
tb.buffer[bufIdx] = tb.buffer[bufIdx + 1];
}
bufNo = tb.Length - 1;
I have determined that the above code is the source of the problem, but I am unable to find out why that is so.
So my question is: Considering the TBBuffer struct, and its contents, does anybody have a clue why this is not working as expected ?
Is there a more efficient way to do this.
Are you looking for array resize?
Array.Resize(ref tb.buffer, newSize);
Just show up your intention to .Net and let it do the work (in the efficient way) for you.
in for loop you use tb.Length. I think it should be tb.buffer.Length:
int bufIdx,bufNo;
for (bufIdx = 0; bufIdx < tb.buffer.Length - 1; bufIdx++)
{
tb.buffer[bufIdx] = tb.buffer[bufIdx + 1];
}
bufNo = tb.Length - 1;
I solved my problem... Rather embarrasing, but the problem was that the data[] of the very last buffer would point at the same as the next-to-last after I did my for () move stunt. After adding a tb.buffer[bufNo].data=new short[4096]; statement everything is back to normal. Thank you for your time, and all the constructive feedback. I will be looking into memory mapped files to see whether this feature will be a better option.
May i ask if the following code i wrote is correct? Basically, i want to create an 2D array, and within each array, i want to have a list of vertices. So if tCount and pCount is 10, i would have 100 different lists storing vertices. The adding of the vertices will be done elsewhere after certain operations are done to determine which list the vertice should be added to.
List<Vertice>[,] lists = new List<Vertice>[tCount, pCount];
for (int i = 0; i < tCount; i++) {
for (int o = 0; o < pCount; o++) {
lists[i,o] = new List<Vertice>(); } }
Pardon me for posting such a simple question, because i have posted a similar qns in another forum and the replies i received kind of confused me. But thanks for reading!
Mitch Wheat- There was no error so far, but i am also not sure if the list is created properly..
Damith- I've seen that before but i do not really understand the code, so i was wondering if the code i typed was correct or not. I feel safer using a code that i understand, although i do understand the benefits of using a 1-liner.
Oberdan Nunes- I need it to be in a 2D array, as it is related to another 2D array of data which i have.
I've met this problem a couple times befores. Here's an example code:
public void moveRight(int x, int y, int rows, int columns)
{
char[,] imatrix = GameInstance.vexedGame.getLastMatrix(); // <-- creating a variable and initializing it.
char letter = imatrix[x, y]; // Doesn't matters
char[,] oldMatrix = imatrix; // Creating a new var that is the same as the variable created before
if (imatrix[x, (y + 1)] == '-')
{
//LINE 1
GameInstance.vexedGame.setLastMatrix(oldMatrix); //Setting the var of this class to the old matrix (until here everything's fine)
imatrix[x, (y + 1)] = letter;
imatrix[x, y] = '-'; //Changing the matix
//LINE 2
GameInstance.vexedGame.setActualMatrix(imatriz); //Setting the actual matrix.
}
}
What happens is that when I put breakpoints in the whole thing, when I get to the //LINE 1, the value is saved with the copy of the matrix before the changes. After I make the changes in //LINE 2, not only the value of imatrix is changed but also the value of the first matrix changes, so the GameInstance.vexedGame.setLastMatrix changes. I don't really know why this happens, and if anybody could help me I would really appreciate it. Thanks!
(Sorry for my bad english)
That's because its an array and arrays are reference type.
When you do
char[,] oldMatrix = imatrix;
this creates a shallow copy. i.e. the address in memory is passed to oldmatrix. Now they are two variables but pointing to same adress in memory. if you change first the second obviously has to change.
To avoid this use loop to copy each value from first to second or
do a deep copy.
Ok so to expand on the other answers here. To do a deep copy you would need to either manually iterate through the values and assign them in that fashion, or use a prebuilt method. Something that could work would be Array.CopyTo(); now this comes with issues as its a one dimensional array copy but that can be worked around with some coding. A helpful slightly different helper function is Array.Copy(); which is meant for copying ranges of values.
The reason it is one dimensional is that there is no telling how jagged the data sizes are within the two dimensions. This therefore is highly dependent on the structure of that multidimensional array. So it falls on the developer to solve that problem unless you can post the structure, for assistance.
Okay, I have this piece of code:
int arrPanelsRequired = 4;
string airport;
int arrPanelsMade = 0;
for (; arrPanelsMade <= arrPanelsRequired; arrPanelsMade++)
{
Panel arrPanelXXX = new Panel();
and I need to replace the XXX with the value of arrPanelsMade. I found several ways to name an object after a variable's value, however, I wasn't able to apply any of them here :(
I don't think it would be a good idea in general, let alone in C#. I can see many arr prefixes, which leads me to the use of an array. I think you might be looking for something like this:
int arrPanelsRequired = 4;
Panel[] panels = new Panel[arrPanelsRequired];
for (int arrPanelsMade = 0; arrPanelsMade < arrPanelsRequired; arrPanelsMade++)
{
panels[arrPanelsMade] = new Panel();
}
What you are trying to do is bad practice. It passes in weakly-typed languages, but in strongly-typed languages such as C#, variables need to be explicitly declared. This helps the compiler to catch errors that can be caused by typos or general development mistakes. For example, if you have a variable arrPanel089, how can you/the compiler know if it has been declared? Strong typing can seem like a constraint when coming from weakly-typed languages, but it is really a great tool that saves you a ton of headache as the developer.
If you want to create a set of panels, store them in an array/list/etc and access them by their index. If you want to give them a key, store them in a dictionary which allows you to access values by key instead.
You should add the panels to a List or array, and access them later by index:
arrPanel = new Panel[arrPanelsRequired];
for( int idx = 0 ; idx < arrPanelsRequired ; idx++)
arrPanel[idx] = new Panel();
You have a couple of things going on here that raise red flags. I'll digress from your question just a bit, because I think you're probably going down the wrong road in a couple of respects.
Drop the "arr" prefix, and just call your variables what they are — don't try to emulate Hungarian Notation unless you've got good reason to do so.
Consider using a while loop instead of a for loop if you're not going to perform your initialization in the loop header.
Now on to your question. No, the language doesn't work like that. Use a List<Panel> class instead. That will allow you to add more panels dynamically without having to predefine how many you want, such as in an array.
What is an efficient way to shrink a two dimensional array to a smaller size in C#?
For example:
var bigArray = new object[100, 100];
var smallArray = new object[10, 10];
bigArray[0, 0] = 1;
bigArray[0, 1] = 2;
...
bigArray[99, 99] = 100000;
startRowIndex = 0;
startColumnIndex = 0;
endRowIndex = 9;
endColumnIndex = 9;
smallArray = bigArray.SomeShirnkingMethod(startRowIndex, startColumnIndex, endRowIndex, endColumnIndex);
How will you write SomeShrinkingMethod() ?
Thanks!
EDIT: I'm simply trying to get the first 10 rows and columns of the bigArray into the smallArray but I'm not sure if a looping through the array is the most efficient method.
You've got to create a new array of the desired size (in your code, you've already done this) and copy the content. I'm not sure what the “shrinking” operation needs to do in your case. However, you cannot modify the dimensions of an existing array.
The function you proposed is defective because it can't know the dimensions of the target array. Either you pass it the dimensions and dimension the new array internally or you pass it the target array and simply copy the contents.
Edit:
In response to your edit: Yes, looping will be the reasonable way to do this and this is also reasonably fast. I'm not aware of a block-copying mechanism in .NET that can be applied to multidimensional arrays.
Depends on what you want your shrinking function to do. You've got to make a new array and do the copy based on whatever your criteria is. My assumption is that you've got a 2d array for a reason, right? The copy could either be trivia (find the next location that has a non-zero value and put it in the next available location in the target) or based on something else. Can you provide more info?
Yes the best method is almost certainly to loop over each cell, although it might be possible to copy a sequence of each 'row'. The method would need to know lower indices of the square to be copied from the source square, and the size (which might be implicit in the destination square definition).