How to use reflection to read an array in an unmanaged structure

B

bill

All,

I have the following:

......

[StructLayout(LayoutKind.Sequential)]
unsafe public struct Example
{
public double we;
public double mu;
public fixed double A1[9 ];
public fixed double A2[9 ];
}

Example ex;
......

I am using reflection to discover the contents of various unmanaged
structures. The one above is just a part of a larger unmanaged
structure. In any case lets suppose an instance of the containing
structure, objBig, has been passed into the code below and that it
contains the structure "Example ex". As I loop through Field members of
objBig and when Member.Name == "Ex" -

......
Object objInside = T.InvokeMember(Member.Name,
BindingFlags.GetField, null, objBig, null);
FieldInfo[] fio = objInside .GetType().GetFields();
foreach (FieldInfo fo in fio)
{
Console.WriteLine("Object name, value is {0}, {1}",
fo.Name, fo.GetValue(o));
}
......

the following is output:

Object name, value is we, 5678
Object name, value is mu, 1234
Object name, value is A1,
ANSNavigationU+Inputs+NavILoads+<A1>e__FixedBuffer1f
Object name, value is A2,
ANSNavigationU+Inputs+NavILoads+<A2>e__FixedBuffer20


I cannot figure out how to "get the value" of the 9 array elements in
either A1 or A2. I also need ot be able to "set the value" of the array
elements. I think the way to set the value of a scalar in the above
example would be like this:

Object[] objNew = new object[] { 4321};
myType.InvokeMember("mu",
BindingFlags.DeclaredOnly | BindingFlags.Public |
BindingFlags.NonPublic |
BindingFlags.Instance | BindingFlags.Static |
BindingFlags.SetField, null, objInside, objNew );

Also, when I inspect the "objInside" with the debugger I can see
exactly what is in the structure for all values whether they be scalars
or arrays or further nested structures. I would have thought it would
be a lot easier the read/write the structure programmatically.

Any help greatly appreciated,

Bill
 
D

Dave Sexton

Hi Bill
I have the following:

.....

[StructLayout(LayoutKind.Sequential)]
unsafe public struct Example
{
public double we;
public double mu;
public fixed double A1[9 ];
public fixed double A2[9 ];
}

Example ex;
.....

I am using reflection to discover the contents of various unmanaged
structures. The one above is just a part of a larger unmanaged
structure. In any case lets suppose an instance of the containing
structure, objBig, has been passed into the code below and that it
contains the structure "Example ex". As I loop through Field members of
objBig and when Member.Name == "Ex" -

.....
Object objInside = T.InvokeMember(Member.Name,
BindingFlags.GetField, null, objBig, null);
FieldInfo[] fio = objInside .GetType().GetFields();
foreach (FieldInfo fo in fio)
{
Console.WriteLine("Object name, value is {0}, {1}",
fo.Name, fo.GetValue(o));
}
.....

the following is output:

Object name, value is we, 5678
Object name, value is mu, 1234
Object name, value is A1,
ANSNavigationU+Inputs+NavILoads+<A1>e__FixedBuffer1f
Object name, value is A2,
ANSNavigationU+Inputs+NavILoads+<A2>e__FixedBuffer20

At this point your OK. The Array Type doesn't override ToString(), so
you're just seeing the class name (implementation of Object.ToString). If
you try to cast the result of GetValue to double[] you should be fine:

double[] value = (double[]) fo.GetValue(o);

(See my next response below about boxing, which applies here as well for the
GetValue method)
I cannot figure out how to "get the value" of the 9 array elements in
either A1 or A2. I also need ot be able to "set the value" of the array
elements. I think the way to set the value of a scalar in the above
example would be like this:

Object[] objNew = new object[] { 4321};
myType.InvokeMember("mu",
BindingFlags.DeclaredOnly | BindingFlags.Public |
BindingFlags.NonPublic |
BindingFlags.Instance | BindingFlags.Static |
BindingFlags.SetField, null, objInside, objNew );

Also, when I inspect the "objInside" with the debugger I can see
exactly what is in the structure for all values whether they be scalars
or arrays or further nested structures. I would have thought it would
be a lot easier the read/write the structure programmatically.

You can set the value of the scalars and the array fields using the
FieldInfo.SetValue method;

Since you're dealing with a structure, however, you'll have to box it before
you set the value otherwise it won't be assigned to your instance. Instead,
it would be assigned to the boxed instance created by the SetValue method.
Here's what you should do:

object o = new Example();
....
fo.SetValue(o, 1023829d);
 
B

bill

Dave,

I got the following exception error message:

"Additional information: Unable to cast object of type
'<ROT_ia_from_isa>e__FixedBuffer1f' to type 'System.Double[]'."

when I tried the cast:

"double[] value = (double[]) fo.GetValue(o);"

Could this be because I am dealing with an unmanaged structure?

Bill

PS: "ROT_ia_from_isa" is the real name of the array, not "A1"


Dave said:
Hi Bill
I have the following:

.....

[StructLayout(LayoutKind.Sequential)]
unsafe public struct Example
{
public double we;
public double mu;
public fixed double A1[9 ];
public fixed double A2[9 ];
}

Example ex;
.....

I am using reflection to discover the contents of various unmanaged
structures. The one above is just a part of a larger unmanaged
structure. In any case lets suppose an instance of the containing
structure, objBig, has been passed into the code below and that it
contains the structure "Example ex". As I loop through Field members of
objBig and when Member.Name == "Ex" -

.....
Object objInside = T.InvokeMember(Member.Name,
BindingFlags.GetField, null, objBig, null);
FieldInfo[] fio = objInside .GetType().GetFields();
foreach (FieldInfo fo in fio)
{
Console.WriteLine("Object name, value is {0}, {1}",
fo.Name, fo.GetValue(o));
}
.....

the following is output:

Object name, value is we, 5678
Object name, value is mu, 1234
Object name, value is A1,
ANSNavigationU+Inputs+NavILoads+<A1>e__FixedBuffer1f
Object name, value is A2,
ANSNavigationU+Inputs+NavILoads+<A2>e__FixedBuffer20

At this point your OK. The Array Type doesn't override ToString(), so
you're just seeing the class name (implementation of Object.ToString). If
you try to cast the result of GetValue to double[] you should be fine:

double[] value = (double[]) fo.GetValue(o);

(See my next response below about boxing, which applies here as well for the
GetValue method)
I cannot figure out how to "get the value" of the 9 array elements in
either A1 or A2. I also need ot be able to "set the value" of the array
elements. I think the way to set the value of a scalar in the above
example would be like this:

Object[] objNew = new object[] { 4321};
myType.InvokeMember("mu",
BindingFlags.DeclaredOnly | BindingFlags.Public |
BindingFlags.NonPublic |
BindingFlags.Instance | BindingFlags.Static |
BindingFlags.SetField, null, objInside, objNew );

Also, when I inspect the "objInside" with the debugger I can see
exactly what is in the structure for all values whether they be scalars
or arrays or further nested structures. I would have thought it would
be a lot easier the read/write the structure programmatically.

You can set the value of the scalars and the array fields using the
FieldInfo.SetValue method;

Since you're dealing with a structure, however, you'll have to box it before
you set the value otherwise it won't be assigned to your instance. Instead,
it would be assigned to the boxed instance created by the SetValue method.
Here's what you should do:

object o = new Example();
...
fo.SetValue(o, 1023829d);
 
D

Dave Sexton

Hi Bill,

Yes, double[] won't work unless it's a double[] Type. I made that
assumption based on your code sample but I didn't realize that the "fixed"
keyword would create a pointer to handle its fixed nature - sorry.

Unfortunately, pointers are outside my area of expertise. I'm not really
sure how to reflect into them, let alone even assign a value to them.

You might have better luck posting in a different newsgroup (maybe a C++
group or something).

Sorry I couldn't help.

--
Dave Sexton

bill said:
Dave,

I got the following exception error message:

"Additional information: Unable to cast object of type
'<ROT_ia_from_isa>e__FixedBuffer1f' to type 'System.Double[]'."

when I tried the cast:

"double[] value = (double[]) fo.GetValue(o);"

Could this be because I am dealing with an unmanaged structure?

Bill

PS: "ROT_ia_from_isa" is the real name of the array, not "A1"


Dave said:
Hi Bill
I have the following:

.....

[StructLayout(LayoutKind.Sequential)]
unsafe public struct Example
{
public double we;
public double mu;
public fixed double A1[9 ];
public fixed double A2[9 ];
}

Example ex;
.....

I am using reflection to discover the contents of various unmanaged
structures. The one above is just a part of a larger unmanaged
structure. In any case lets suppose an instance of the containing
structure, objBig, has been passed into the code below and that it
contains the structure "Example ex". As I loop through Field members of
objBig and when Member.Name == "Ex" -

.....
Object objInside = T.InvokeMember(Member.Name,
BindingFlags.GetField, null, objBig, null);
FieldInfo[] fio = objInside .GetType().GetFields();
foreach (FieldInfo fo in fio)
{
Console.WriteLine("Object name, value is {0}, {1}",
fo.Name, fo.GetValue(o));
}
.....

the following is output:

Object name, value is we, 5678
Object name, value is mu, 1234
Object name, value is A1,
ANSNavigationU+Inputs+NavILoads+<A1>e__FixedBuffer1f
Object name, value is A2,
ANSNavigationU+Inputs+NavILoads+<A2>e__FixedBuffer20

At this point your OK. The Array Type doesn't override ToString(), so
you're just seeing the class name (implementation of Object.ToString).
If
you try to cast the result of GetValue to double[] you should be fine:

double[] value = (double[]) fo.GetValue(o);

(See my next response below about boxing, which applies here as well for
the
GetValue method)
I cannot figure out how to "get the value" of the 9 array elements in
either A1 or A2. I also need ot be able to "set the value" of the array
elements. I think the way to set the value of a scalar in the above
example would be like this:

Object[] objNew = new object[] { 4321};
myType.InvokeMember("mu",
BindingFlags.DeclaredOnly | BindingFlags.Public |
BindingFlags.NonPublic |
BindingFlags.Instance | BindingFlags.Static |
BindingFlags.SetField, null, objInside, objNew );

Also, when I inspect the "objInside" with the debugger I can see
exactly what is in the structure for all values whether they be scalars
or arrays or further nested structures. I would have thought it would
be a lot easier the read/write the structure programmatically.

You can set the value of the scalars and the array fields using the
FieldInfo.SetValue method;

Since you're dealing with a structure, however, you'll have to box it
before
you set the value otherwise it won't be assigned to your instance.
Instead,
it would be assigned to the boxed instance created by the SetValue
method.
Here's what you should do:

object o = new Example();
...
fo.SetValue(o, 1023829d);
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top