|
I need to call an unmanaged function that takes, basically, a void pointer to a buffer. I've got the transfer to the unmanaged DLL working by passing a byte [] and letting .NET marshal. However, the buffer may contain different data structures on different calls since it's a kind of generic entry point with the exact function specified in the first field. In C I would do something like this:
char buf[1000];
struct Header {
int cmd;
int flags;
int param;
};
struct Cmd1SpecificData {
double param1ForCommand1;
short param2ForCommand1;
short param3ForCommand1;
// and so on...
};
void foo()
{
Header *header = (Header *)buf;
Cmd1SpecificData = (Cmd1SpecificData *)(header + 1);
header->cmd = 1;
header->flags = 999;
Cmd1SpecificData->param1ForCommand1 = 123.456;
APICALL(buf);
}
APICALL can now look at the first field and figure out what to do.
In C# I don't quite know how to do this. I have a byte [] which is the equivalent of the char buf[] but how do I cast pointers into the byte []? I couldn't find a simple way to copy data from a struct to a byte [] or how to use a MemoryStream to stream the data into the byte [].
My questions:
1) What's the best way of getting the contents of a struct into a byte array? Note that I'll need to get different structures chained together so I might need to put the contents of the structs at specific offsets in the byte array.
2) Is there a fundamentally better way of getting .NET data to an API of this sort? Maybe I should do the marshalling myself and convert everything to a pointer before calling the unmanaged code?
Thanks,
Andrew Queisser
|
|
|
|
|
Well, to copy a struct to a byte[], you need some marshaling code..It uses the Marshal class (as if that wasn't obvious) to allocate some memory..Like this:
(i usually declare methods like this as an instance method and a static method with a parameter of whatever type it's defined in)
<pre><br />
public byte[] ToBytes()<br />
{<br />
byte[] buff = new byte[Marshal.SizeOf(typeof(MyType))];<br />
GCHandle handle = GCHandle.Alloc(buff, GCHandleType.Pinned);<br />
Marshal.StructureToPtr(this, handle.AddrOfPinnedObject(), false);<br />
handle.Free();<br />
return buff;<br />
}<br />
</pre><br />
<br />
That code will marshal the struct to a byte[], and from that code, the code for marshaling back to a struct comes easy:<br />
<br />
<code lang=cs><pre><br />
public static MyType FromBytes(byte[] buff)<br />
{<br />
GCHandle handle = GCHandle.Alloc(buff, GCHandleType.Pinned);<br />
MyType mt = (MyType)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(MyType));
handle.Free();<br />
return mt;<br />
}<br />
</pre><br />
<br />
<br />
Now as for chaining structures together, you can do that yourself using Array.Copy() and copying into a byte[]<br />
<br />
Passing back the data as an IntPtr requires only slight modification to the original functions:<br />
<br />
<code lang=cs><pre><br />
public IntPtr ToIntPtr()<br />
{<br />
byte[] buff = new byte[Marshal.SizeOf(typeof(MyType))];<br />
IntPtr handle = Marshal.AllocHGlobal(buff.Length);<br />
Marshal.StructureToPtr(this, handle, true);
return handle;<br />
}<br />
<br />
public static MyType FromIntPtr(IntPtr ptr)<br />
{<br />
MyType mt = (MyType)Marshal.PtrToStructure(ptr, typeof(MyType));
return mt;<br />
}<br />
Note: That code is not 100% guaranteed to compile or work, I didn't test it very much, but it should work, and the basic concept is more or less correct.
If you have any more questions, feel free to ask.
|
|
|
|
|
|
I need to allow a user to select a portion of an image for cropping. Once this selection frame has been created they also need to be able to resize and rotate it. The behavior I am looking for is similar to drawing rectangles in Word or selecting objects in Visio.
Any insight on how to do this?
Is there already a control available that I missed?
I tried taking nashcontrol's RectTracker http://www.codeproject.com/cs/miscctrl/CSharpRectTracker.asp[^] and converting it to take a Rectangle instead of a Control, which worked but not sure what to do about rotation. Matrix offers nice transforms for rotating the region but once rotated how do I find out if the mouse is at one of the "resize grips" to change the cursor? There must be an easy way lots of apps do this..
Thanks
|
|
|
|
|
Hi all,
I have a datagrid with a checkbox item in the header and i'm implementing a "select all" function which when select would select all other checkboxes on the form...
i am implementing the selectall function in javascript as such
function selectAll(obj)
{
if (obj.checked==true)
{
for(i=0; i<(document.forms[0].elements.length); i++)
{
...
all is working fine but i would like to change the text of the obj checkbox but i cant...
i tried obj.text = 'removeAll' but that doesnt work
any ideas?
|
|
|
|
|
Please don't double post.
---
b { font-weight: normal; }
|
|
|
|
|
Hello,
How can I prevent my control to be serialized in design-mode?
Thank you in advance.
Goran
|
|
|
|
|
|
So, when I move the control in design-mode I would like the position settings not to be updated.
|
|
|
|
|
You're serializing a control? I didnt even think that you could serialize a control.
|
|
|
|
|
Actually, I would like to check in the constructor of my control where I am - in designer or in runtime. How can i do that?
|
|
|
|
|
Do you mean that you want to check to see if youre running in debug or release mode?
|
|
|
|
|
No. The control can be placed to the form in design mode in MSVS.NET IDE - design-mode or the application can be run - run-mode.
|
|
|
|
|
Try this:
if (DesignMode)
{
}
|
|
|
|
|
Ummm....What???
If you move the control, you're changing the position! When you move the control in the designer, the only property of the control being changed is Location. So how do you want to both move and not move the control? What are you really trying to do with this?
RageInTheMachine9532
"...a pungent, ghastly, stinky piece of cheese!" -- The Roaming Gnome
|
|
|
|
|
Actually, I would like to check in the constructor of my control where I am - in design-mode in MSVS.NET IDE or in runtime, which means my application is started. How can I check that?
|
|
|
|
|
Just check the DesignMode property. It'll be true if you're in DesignMode and false if in Runtime or other.
RageInTheMachine9532
"...a pungent, ghastly, stinky piece of cheese!" -- The Roaming Gnome
|
|
|
|
|
Hello,
I have a simple questions: How can I check inside the control where I am - in design mode or run-time mode?
Thank you in advance.
Goran
|
|
|
|
|
Well if you want to know what the parent of the control is just use the Parent property of the control. If you want to know where the mouse is, use the MousePosition property of the control.
|
|
|
|
|
Actually, I would like to check in the constructor of my control where I am - in designer or in runtime. How can i do that?
|
|
|
|
|
Say what? None of your code is executed during design time.
|
|
|
|
|
|
Actually, that's not true. When you drop an instance of your control on a form, the code IS executed.
RageInTheMachine9532
"...a pungent, ghastly, stinky piece of cheese!" -- The Roaming Gnome
|
|
|
|
|
If your talking about your controls position on the form, AFAIK, you can't do that in the constructor. I don't think your control has it's Location property set until after the constructor returns.
I could be wrong though...
RageInTheMachine9532
"...a pungent, ghastly, stinky piece of cheese!" -- The Roaming Gnome
|
|
|
|
|
Every conrol has a property called DesignMode
you can check
if (DesignMode)
{
}
else
{
}
-
Drew
|
|
|
|