I've done a fair amount of P/Invoking but for some reason I'm having problem with this one case. I need to define a delegate because I need to dynamically create the delegate at runtime using Marshal.GetDelegateForFunctionPointer(). Anyway, I don't think that is directly related to my problem, it is more to do with how I declare the delegate and use it. So say I have this:
[StructLayout(LayoutKind.Sequential, Pack = 4)]
public struct MyStruct
public bool Value1;
public int Value2;
public IntPtr Ptr1;
public IntPtr Ptr2;
public delegate void Foo([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)]
ref MyStruct structs, int arrayLength);
Note that the structs array is both in and out, so I need to use ref (the native method modifies the structures). Now when I do this:
var structs = new MyStruct;
for (var idx = 0; idx < structs.Length; idx++)
structs[idx].Value2 = idx;
Foo(ref structs, structs.Length);
...The call fails. Note I simplified the code in this example but in the real code the function returns a value indicating failure.
Now if I change the delegate declaration and the way I call it to the following...
public delegate void Foo(IntPtr structs, int arrayLength);
fixed (MyStruct* pStructs = &structs)
The call succeeds. It seems that the two should be the same from the native code's perspective. I would prefer if I don't have to use unsafe methods and the need to mark the assembly as using unsafe code. So what is wrong with my 1st delegate declaration?
I think this might be the problem:
SizeParamIndex = 1
Does that mean the size is 1 byte or am I mistaken?
I don't think you need the ref in your first delegate signature, unless the native method uses a pointer to an array (double indirection).
If I do that, the call succeeds but the contents of the array of structures are not updated by the native function. Or at least, after the call, I am not seeing the changes on the managed side. Remember it needs to be in/out.
What SizeParamIndex means is that it indicates the index of the parameter that defines the number of structures in the array. So I set it to 1 in this case because my second parameter (starting from 0), indicates the number of structures. In native function calls, that is often the way that the length of arrays are indicated. See here for more details.
Maybe try marking it with explicit [In, Out] attributes? I'm fairly sure it shouldn't be ref for this scenario (unless, as I said, it's a double pointer) but it might not marshal the results back by default. Adding the attribute would take care of that, I think.
Yes, that actually did it! I forgot that you could mark it like that. For some reason I thought "[In, Out]" is the same as "ref", which of course isn't true.
Thanks for your help!
try using a binary, contex helper method. use a mux/demux for the in/out, sent in one direction by decodes to di-directiocal com.
Comments have been closed since this content was published more than 30 days ago, but if you'd like to continue the conversation, please create a new thread in our Forums, or Contact Us and let us know.