[Mono-list] Custom Marshalling
I've implemented some custom marshalling for an external call so that the parameters being sent gets massaged as required by the external routine. In addition, it is supposed to massage data after the call. However, while it will do so on the way out, it's not being driven the other way. I found that if I specified ref on the parameters being passed then the MarshalManagedToNative method will not be driven, if I specify nothing or out then neither the ToNative or ToManaged methods are being called. [DllImport(libname, EntryPoint = scumbag)] private unsafe static extern void scumbag (ref XXXCB cb, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof (AdaByteBuffer))] XXXBuffer fb, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof (AdaByteBuffer))] XXXBuffer rb, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof (AdaByteBuffer))] XXXBuffer sb, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof (AdaByteBuffer))] XXXBuffer vb, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof (AdaIntBuffer))] XXXIB ib); Neale ___ Mono-list maillist - [EMAIL PROTECTED] http://lists.ximian.com/mailman/listinfo/mono-list
Re: [Mono-list] Custom Marshalling
I'm a little confused by your description. I am not trying to be difficult, but you use the pronoun it in many places where the antecedent is unclear. Also, the phrase on its way out is not clear. Perhaps if you demonstrated the problem using a P/Invoke method with fewer parameters and explained any problems with in, out, and ref parameters separately, I could better understand. Marcus On Thursday 28 October 2004 1:12 pm, [EMAIL PROTECTED] wrote: I've implemented some custom marshalling for an external call so that the parameters being sent gets massaged as required by the external routine. In addition, it is supposed to massage data after the call. However, while it will do so on the way out, it's not being driven the other way. I found that if I specified ref on the parameters being passed then the MarshalManagedToNative method will not be driven, if I specify nothing or out then neither the ToNative or ToManaged methods are being called. [DllImport(libname, EntryPoint = scumbag)] private unsafe static extern void scumbag (ref XXXCB cb, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof (AdaByteBuffer))] XXXBuffer fb, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof (AdaByteBuffer))] XXXBuffer rb, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof (AdaByteBuffer))] XXXBuffer sb, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof (AdaByteBuffer))] XXXBuffer vb, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof (AdaIntBuffer))] XXXIB ib); ___ Mono-list maillist - [EMAIL PROTECTED] http://lists.ximian.com/mailman/listinfo/mono-list
RE: [Mono-list] Custom Marshalling
I'll attempt to think before I type this time :-) I have a a C routine I wish to call that takes the following parameters: typedef struct XXXCB { short a; char b[2]; }; void scumbag(XXXCB *cb, char *v); for our purposes v is an arbitrarily long string of bytes in the range 0x00-0x7f. Depending on the contents of b variable v can be input to or output from the function scumbag. In C# I'd code XXXCB as: public struct XXXCB { public short a; [MarshalAS(UnmanagedType.ByValArray, SizeConst=2)} public byte[] b; } Now, because the variable v can be a different length of each call (up to 32K is size) I can't use MarshalAs(UnmanagedType.ByValArray) as mcs demands that SizeConst= be coded (using SizeParamIndex= doesn't work, in fact I don't think it's supported). So what I've done is created a class XXXByteBuffer to Marshal the data using ICustomMarshaler. Therefore, I've coded the call prototype as: [DllImport(libname, EntryPoint = scumbag)] private static extern void scumbag (ref XXXCB cb, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof (XXXByteBuffer))] v); I created the necessary methods (like ManagedToNative and NativeToManaged) in XXXByteBuffer. When I call scumbag using parameters conforming to the above prototype the ManagedToNative method is being driven prior to the call but NativeToManaged is not being called on the return. If I change the prototype to specify ref v or out v then neither method is being driven. Neale -Original Message- I'm a little confused by your description. I am not trying to be difficult, but you use the pronoun it in many places where the antecedent is unclear. Also, the phrase on its way out is not clear. Perhaps if you demonstrated the problem using a P/Invoke method with fewer parameters and explained any problems with in, out, and ref parameters separately, I could better understand. ___ Mono-list maillist - [EMAIL PROTECTED] http://lists.ximian.com/mailman/listinfo/mono-list
RE: [Mono-list] Custom Marshalling
You're making this far too difficult on yourself. See below. On Thu, 2004-10-28 at 19:57, [EMAIL PROTECTED] wrote: I'll attempt to think before I type this time :-) I have a a C routine I wish to call that takes the following parameters: typedef struct XXXCB { short a; char b[2]; }; void scumbag(XXXCB *cb, char *v); snip/ In C# I'd code XXXCB as: public struct XXXCB { public short a; [MarshalAS(UnmanagedType.ByValArray, SizeConst=2)} public byte[] b; } Good declaration. Now, because the variable v can be a different length of each call (up to 32K is size) I can't use MarshalAs(UnmanagedType.ByValArray) as mcs demands that SizeConst= be coded (using SizeParamIndex= doesn't work, in fact I don't think it's supported). There's a bigger problem: ByValArray doesn't mean what you think it does. At least, not entirely. ByValArray means that it's a contiguous blob of memory, which is why you used it in your XXXCB structure declaration -- you needed to specify the size of b. Perfectly natural. However, it means the *same thing* no matter where it's applied. So applied to a method argument, it means push a blob of data SizeConst bytes onto the stack). This is NOT what C does; C always pushes a *pointer* to an array onto the stack. Compare these two (C-like) declarations: // ByValArray equivalent void scumbag (XXXCB *cb, struct {char data[SOME_LENGTH];} v); // LPArray equivalent: void scumbag (XXXCB *cb, char *v); The first one probably isn't valid C, and certainly isn't what you want when invoking existing C code (but may be useful when dealing with other languages). Obviously, you don't want ByValArray for method arguments. You want LPArray. Fortunately, this is the default, and marshals the number of elements inside the array: [DllImport (libname)] private static extern void scumbag (ref XXXCB cb, byte[] v); Usage is straight-forward: XXXCB cb = new XXXCB(); scumbag (ref cb, Encoding.ASCII.GetBytes (this is my v arg1)); scumbag (ref cb, Encoding.ASCII.GetBytes (this is another v)); Consequently, you don't need the custom marshaler. - Jon ___ Mono-list maillist - [EMAIL PROTECTED] http://lists.ximian.com/mailman/listinfo/mono-list
Re: [Mono-list] Custom marshalling
Unfortunately, UnmanagedMarshal.DefineCustom is a Mono-only class and not part of .NET. The normal .NET mechanism is to create a custom attribute using CustomAttributeBuilder to obtain an instance of MarshalAsAttribute with the custom marshaler specified. That does not seem to work under Mono. It is possible to implement custom marshalers without having to use reflection, as long as you know what what types you want to marshal to what at compile time. public class MyMarshal: ICustomMarshaler {...} private static extern void PrintObject( [MarshalAs( UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(MyMarshal ) )] object o ); On Sunday 25 July 2004 5:12 pm, Alan Jenkins wrote: As far as I can tell, Mono supports custom marshalling outside of function calls (like PInvoke), - ie using Marshal.StructToPtr and PtrToStruct, but you have to use UnmanagedMarshal.DefineCustom, which would involve reflection of some sort - possibly creating your class with custom marshalled fields by reflection. Does UnmanagedMarshal.DefineCustom work? Is it efficient (as far as custom marshalling can be)? Is it supported (or undocumented and likely to disappear/break)? Would it be (technically) possible to access its functionality through an attribute, in the same way that non-custom marshalling is done? Is this likely to happen? ___ Mono-list maillist - [EMAIL PROTECTED] http://lists.ximian.com/mailman/listinfo/mono-list
[Mono-list] Custom marshalling
As far as I can tell, Mono supports custom marshalling outside of function calls (like PInvoke), - ie using Marshal.StructToPtr and PtrToStruct, but you have to use UnmanagedMarshal.DefineCustom, which would involve reflection of some sort - possibly creating your class with custom marshalled fields by reflection. Does UnmanagedMarshal.DefineCustom work? Is it efficient (as far as custom marshalling can be)? Is it supported (or undocumented and likely to disappear/break)? Would it be (technically) possible to access its functionality through an attribute, in the same way that non-custom marshalling is done? Is this likely to happen? Alan ___ Mono-list maillist - [EMAIL PROTECTED] http://lists.ximian.com/mailman/listinfo/mono-list