Passing NULL for the ref / out parameter of a COM interface method

How to pass NULL to a COM interface method parameter if it is defined as [In, Out] ref int pchEaten ?

For example, consider the following interface:

 [ComImport, Guid ("000214E6-0000-0000-C000-000000000046")] [InterfaceType (ComInterfaceType.InterfaceIsIUnknown)] internal interface IShellFolder { void ParseDisplayName ( [In] IntPtr hwnd, [In] IBindCtx pbc, [In, MarshalAs (UnmanagedType.LPWStr)] string pszDisplayName, [In, Out] ref uint pchEaten, [Out] out PIDLIST ppidl, [In, Out] ref SFGAO pdwAttributes); // ... } 

MSDN says the following about the pchEaten parameter: a pointer to a ULONG value that receives the number of characters of the display name that has been parsed. If your application does not need this information, set pchEaten to NULL and no value will be returned. The pdwAttributes parameter pdwAttributes also be set to NULL.

However, when I ParseDisplayName method from C #, I see no way to pass a null value to the ref parameter.

If I called functions from a DLL, I could import the function several times: one with the IntPtr parameter, IntPtr with the correct signature, and choose the overload depending on whether I need to send and receive values. However, if I try to import the same method several times into COM, it will not work, since the order of the methods is critical and the function pointers will be offset.

Question : How to make it possible to call a COM method with both a value and a NULL value in / out?

Note : this is just an example. I know that I can create a dummy variable, pass it to the ref parameter and ignore the return value. However, the behavior of the method may depend on whether the value is NULL, a non-zero value can lead to performance degradation, etc., so I would like to avoid this.

+4
source share
2 answers

It seems to me that you are probably trying too hard to avoid pointers. C # language supports them just fine, you can declare an argument as [In] uint* pchEaten . Now that you have all the options available in your native language, you can pass &local as well as null . Where local must be the local variable of the calling method so that the pointer is stable and you don’t have to worry about binding.

But yes, you need to declare the method unsafe. Of course, this is not when you program it correctly :)

+3
source

You can override the interface, for example:

 internal interface IShellFolder { void ParseDisplayName ( [In] IntPtr hwnd, [In] IBindCtx pbc, [In, MarshalAs (UnmanagedType.LPWStr)] string pszDisplayName, IntPtr pchEaten, [Out] out PIDLIST ppidl, [In, Out] ref SFGAO pdwAttributes); // ... } 

And called like this if you want to pass null:

 ParseDisplayName(...., IntPtr.Zero, ...); 

Or, if you want to pass a uint value:

 IntPtr p = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(uint))); uint i = 1234; Marshal.StructureToPtr(i, p, false); ParseDisplayName(...., p, ...); i = (uint)Marshal.PtrToStructure(p, typeof(uint)); // read the value back Marshal.FreeHGlobal(p); 
+4
source

All Articles