P / Invoke带有可选的out指针

时间:2013-05-24 23:28:37

标签: c# winapi pinvoke

如何调用像StartXpsPrintJob这样的方法,它可以选择返回指向COM对象的指针,具体取决于是否为OUT参数传递了NULL。

C ++中的示例是使用printTicketStream设置NULL

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

我知道我可以创建可选参数IntPtr而不是out IntPtr并只传递IntPtr.Zero,但这需要此函数的四个P / Invoke签名来包含所有选项,更不用说调用代码的样子了。

1 个答案:

答案 0 :(得分:0)

由于参数实际上是指向将保存结果的指针的指针,因此请分配指针并将其作为IntPtr传递。

示例签名:

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

使用示例:

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