C # Interop: Out params, которые также могут быть нулевыми - PullRequest
1 голос
/ 02 октября 2009

Рассмотрим следующий DllImport:

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

На самом деле это ссылка на функцию стиля C, например:

int DoSomething(void* SomeParam); 

Учтите, что SomeParam является параметром "out", но также может иметь значение NULL. Функция C ведет себя по-разному, если параметр равен NULL. Поэтому я, вероятно, хотел бы:

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

Но, если я сделаю это out-параметром в своем импорте, я не смогу передать его NULL, т.е.

int retVal = DoSomething(IntPtr.Zero)

Какие у меня есть варианты?

Ответы [ 5 ]

8 голосов
/ 02 октября 2009

Если вы пытаетесь передать значение, тогда out - не правильное ключевое слово; измените его на ref. Вам все равно потребуется явно передать переменную, но это может быть null ссылка.

Например ...

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

Затем вы можете назвать это так:

IntPtr retVal = IntPtr.Zero;

DoSomething(ref retVal);

1012 * Тем не менее * Что говорит вам, что это должно быть либо out, либо ref? Передача IntPtr как out или ref действительно похожа на передачу двойного указателя. На самом деле было бы более уместно передать параметр как IntPtr. Типичной процедурой является либо выделение необходимой памяти в управляемом коде и передача IntPtr, представляющего эту выделенную память, либо IntPtr.Zero, чтобы представить нулевой указатель. Вам не нужно передавать IntPtr как out или ref, чтобы отправлять данные обратно в .NET; это нужно сделать только в том случае, если вызываемая функция на самом деле изменит адрес указателя .

0 голосов
/ 02 октября 2009

Лично я бы импортировал эту функцию дважды, первый раз с параметром 'out', второй с '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);

Это решит вашу проблему и сделает код более читабельным.

0 голосов
/ 02 октября 2009

Я столкнулся с этим один раз. Я закончил маршалингом указателя сам (см. Члены маршала для библиотечных функций для этого).

0 голосов
/ 02 октября 2009

Каково намерение передать NULL? Предполагается ли вызывать метод как обычно, но просто не устанавливать выходной параметр?

В этом случае, я думаю, я бы просто обернул метод extern с перегрузкой в ​​C #. Эта перегрузка (без параметра out) будет выглядеть так:

public void DoSomething()
{
    IntPtr dummy;
    DoSomething(out dummy);
}
0 голосов
/ 02 октября 2009

Я не понимаю, в чем проблема ....

Это работает:

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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...