unknownuser
unknownuser

Reputation: 800

C# Interop: Out params that can also be null

Consider the following DllImport:

[DllImport("lulz.so")]
public static extern int DoSomething(IntPtr SomeParam);

This is actually referencing a C style function like this:

int DoSomething(void* SomeParam); 

Consider that SomeParam is an "out" param, but can also be NULL. The C function behaves differently if the param is NULL. So I would probably want:

[DllImport("lulz.so")]
public static extern int DoSomething(out IntPtr SomeParam);

But, if I make it an out param in my import, I cannot pass it NULL, i.e. I can't do this:

int retVal = DoSomething(IntPtr.Zero)

What are my options here?

Upvotes: 2

Views: 4393

Answers (5)

elder_george
elder_george

Reputation: 7879

Personally, I'd import this function twice, first time with 'out' parameter, second with 'in'.

[DllImport("lulz.so")]
public static extern int DoSomething(out IntPtr SomeParam);

// call as DoSomethingWithNull(IntPtr.Zero)
[DllImport("lulz.so", EntryPoint="DoSomething")]
public static extern int DoSomethingWithNull(IntPtr SomeParam);

This will solve your problem and will make code more readable.

Upvotes: 0

Adam Robinson
Adam Robinson

Reputation: 185663

If you're trying to pass a value, then out is not the right keyword; change it to ref. You'll still need to explicitly pass a variable, but it can be a null reference.

For example...

[DllImport("lulz.so")]
public static extern int DoSomething(ref IntPtr SomeParam);

You can then call it like this:

IntPtr retVal = IntPtr.Zero;

DoSomething(ref retVal);

However

What is telling you that it needs to be either out or ref? Passing an IntPtr as out or ref is really akin to passing a double pointer. It would actually seem more appropriate to pass the parameter as an IntPtr.

The typical procedure is either to allocate the necessary memory in managed code and pass an IntPtr representing that allocated memory, or IntPtr.Zero to represent a null pointer. You do not need to pass the IntPtr as out or ref in order to send data back to .NET; you only need to do that if the function you're calling would actually change the pointer's address.

Upvotes: 8

Joshua
Joshua

Reputation: 43317

I ran into this once. I ended up marshaling the pointer myself (see Marshal Members for the library functions to do so).

Upvotes: 0

John Saunders
John Saunders

Reputation: 161811

What's the intention of passing NULL? Is it intended to call the method as usual, but to simply not set the output parameter?

In that case, I think I'd just wrap the extern method with an overload in C#. That overload (without the out parameter) would be like this:

public void DoSomething()
{
    IntPtr dummy;
    DoSomething(out dummy);
}

Upvotes: 0

recursive
recursive

Reputation: 86134

I don't understand what the problem is....

This runs:

private void button2_Click(object sender, EventArgs e) {
    object bar;
    Method(out bar);

    bar = IntPtr.Zero;
    Method(out bar);
}

private void Method(out object foo) {
    foo = null;
}

Upvotes: 0

Related Questions