How to pass NULL to a parameter of a COM interface method if it is defined like [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 was parsed. If your application does not need this information, set pchEaten to NULL, and no value will be returned. The pdwAttributes
parameter can also be set to NULL.
However, when I call the ParseDisplayName
method from C#, I see no way to pass null
to a ref parameter.
If I were calling functions from a DLL, I could import a function multiple times: one with IntPtr
parameter, one with proper signature, and choose the overload depending on wether I need to pass and receive the values. However, if I try importing the same method multiple times in COM, it won't work as the order of methods is crucial and function pointers will shift.
Question: How to make calling a COM method both with a value and NULL of an in/out parameter possible?
Note: This is just an example. I know I can create a dummy variable, pass it to a ref
parameter and ignore the returned value. However, behavior of a method may depend on wether the value is NULL, non-null value may incur performance costs etc., so I'd like to avoid it.
You can redefine the interface like this 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 call it like this if you want to pass null:
ParseDisplayName(...., IntPtr.Zero, ...);
Or like this 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);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With