Calling Win API in C# with P/Invoke when _Out_ parameters can be NULL or non-NULL -
i'm new c# , i'm learning c# write small tools.
there many windows api pointer parameters null or non-null depends on different use case. question is, how declare such parameters in dllimport?
for example:
long querydisplayconfig( _in_ uint32 flags, _inout_ uint32 *pnumpatharrayelements, _out_ displayconfig_path_info *ppathinfoarray, _inout_ uint32 *pnummodeinfoarrayelements, _out_ displayconfig_mode_info *pmodeinfoarray, _out_opt_ displayconfig_topology_id *pcurrenttopologyid );
when flags
qdc_database_current
, last parameter pcurrenttopologyid
must not null. when flags
other value, pcurrenttopologyid
must null.
if parameter declared "out intptr" or "ref intptr", in order api can change referred memory. if passing intptr.zero required api, api call return error_noaccess.
[dllimport(user32_filename, setlasterror=true)] internal static extern int querydisplayconfig( [in] qdc_flags flags, [in, out] ref uint32 pnumpatharrayelements, [out] displayconfig_path_info[] ppathinfoarray, [in, out] ref uint32 pnummodeinfoarrayelements, [out] displayconfig_mode_info[] pmodeinfoarray, out intptr pcurrenttopologyid );
if parameter declared "intptr", intptr.zero can passed null pointer. if passing intptr, api call return error_noaccess.
[dllimport(user32_filename, setlasterror=true)] internal static extern int querydisplayconfig( [in] qdc_flags flags, [in, out] ref uint32 pnumpatharrayelements, [out] displayconfig_path_info[] ppathinfoarray, [in, out] ref uint32 pnummodeinfoarrayelements, [out] displayconfig_mode_info[] pmodeinfoarray, intptr pcurrenttopologyid );
i don't expect declaring different version of extern functions, when number of different parameters combination can numerous.
any suggestion?
when have optional parameter enum, have here, think there little alternative declare 2 separate overloads. overload use pass null declares parameter this:
intptr pcurrenttopologyid
you pass intptr.zero
when calling overload.
the other overload, 1 call when pass non-null value declares parameter this:
out displayconfig_topology_id pcurrenttopologyid
where displayconfig_topology_id
c# enum
base type of int
.
your code gets second variant wrong because declare out intptr pcurrenttopologyid
. intptr
wrong size on 64 bit (8 bytes rather 4).
if wish declare single p/invoke , not use overloads transfer work elsewhere. have pick first option:
intptr pcurrenttopologyid
fine when want pass intptr.zero
. when need pass address of enum variable need pin variable using gchandle
, addrofpinnedobject
. possible yet more boilerplate. so, take pick!
Comments
Post a Comment