简体   繁体   中英

P/Invoke with optional out pointer

How can I call a method like StartXpsPrintJob , which optionally returns a pointer to a COM object, depending upon whether NULL is passed for the OUT parameter.

Example in C++ would be a call with printTicketStream set NULL :

 IXpsPrintJob *job = NULL; IXpsPrintJobStream *jobStream = NULL; hr = StartXpsPrintJob( printerName, NULL, NULL, NULL, completionEvent, NULL, 0, &job, &jobStream, /* _Out_ IXpsPrintJobStream **printTicketStream */ NULL); 

I know I could make the optional parameter IntPtr rather than out IntPtr and just pass IntPtr.Zero , but that would require four P/Invoke signatures of this function to encompass all of the options, not to mention what the calling code would look like.

Since the parameter is really a pointer to a pointer which will hold the result, allocate a pointer and pass it as IntPtr .

Example signature:

[DllImport("XpsPrint.dll", EntryPoint = "StartXpsPrintJob", PreserveSig = false)]
private static extern void StartXpsPrintJob(
    // other parameters omitted for brevity
    IntPtr printTicketStream);

Example use:

IXpsPrintJobStream ticketStream = null;
bool getTicketStream = false;

IntPtr ppTicketStream = IntPtr.Zero;
if (getTicketStream)
{
    ppTicketStream = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(IntPtr)));
    Marshal.StructureToPtr(IntPtr.Zero, ppTicketStream, false);
}

StartXpsPrintJob(ppTicketStream);

if (getTicketStream)
{
    IntPtr pTicketStream = (IntPtr)Marshal.PtrToStructure(ppTicketStream, typeof(IntPtr));
    ticketStream = (IXpsPrintJobStream)Marshal.GetTypedObjectForIUnknown(pTicketStream, typeof(IXpsPrintJobStream));
    Marshal.FreeCoTaskMem(ppTicketStream);
}

//ticket stream now has the result from StartXpsPrintJob or null, if it was not requested

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM