Вызов c-метода с массивом c-style в качестве параметра из C # .NET

2

У меня есть метод, определенный в неуправляемой DLL:

int foo(somestruct * vector, int size)

Как я могу вызвать этот метод из С#? По сути, я хочу завершить следующий фрагмент кода:

[StructLayout(LayoutKind.Sequential), Serializable]
public struct somestruct
{
    //Whatever.
};

[DLLImport("some.dll")]
public static extern int foo( ???? );

Спасибо.

Теги:

5 ответов

3
Лучший ответ

Это намного проще, чем вы думаете.

[DLLImport("some.dll")]
public static extern int foo(somestruct[] vector, int size);

Единственное, что нужно учитывать, это направление маршалинга. Время выполнения делает некоторые решения о том, следует ли маршалировать массив перед вызовом, после вызова или и тем, и другим. Чтобы убедиться в правильности решения, вы можете использовать атрибуты In и/или Out.

[DLLImport("some.dll")]
public static extern int foo([In] somestruct[] vector, int size);
// will only marshal the array to native memory before the call

[DLLImport("some.dll")]
public static extern int foo([Out] somestruct[] vector, int size);
// will only marshal the array to managed memory after the call

[DLLImport("some.dll")]
public static extern int foo([In, Out] somestruct[] vector, int size);
// will marshal the array both ways

С другой стороны, если somestruct blittable, то маршалинг не требуется, так как время выполнения может просто привязывать array и передать указатель на управляемую копию.

2

Посмотрите атрибут DllImport:

http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.dllimportattribute.aspx

Это именно то, что вам нужно.

Этот учебник: http://msdn.microsoft.com/en-us/library/hk9wyw21.aspx может быть специально для вашей проблемы.

Еще одна ссылка на проблему: http://msdn.microsoft.com/en-us/library/z6cfh6e6.aspx#cpcondefaultmarshalingforarraysanchor2

  • 1
    Это то, что я пытаюсь сделать. Возможно, мне следует уточнить вопрос.
  • 0
    @Vlad - поскольку eckesicle писал, что «MarshalAs Unmanaged.LPArray» не работал должным образом, я предполагаю, что использование DllImport здесь не является проблемой.
Показать ещё 2 комментария
0

Да, насколько я знаю, вы должны маршевать этот массив вручную, используя IntPtr. Не так давно был вопрос, посмотрите здесь. Другой подход заключается в том, чтобы переписать собственный код в управляемый С++ или создать С++-оболочку, которая вызывает DLL для вас.

0

LPArray должен быть правильным.

Правильно ли определено определение somestruct? Является ли ваш C int 32 бита, или у вас, возможно, есть несоответствие?

Возможно, опубликуйте определение, которое вы попробовали и в вопросе, это может прояснить ситуацию.

  • 0
    Спасибо, обновил вопрос.
0

.NET interop не имеет проблем со структурой, а также с неуправляемым массивом. Вы можете определить struct в С# и рассказать его в макет последовательно через пользовательский атрибут, чтобы он мог сопоставить вам структуру C. Для массива вы можете использовать LPArray или даже IntPtr и самостоятельно его сортировать. Вам нужно будет использовать атрибут DllImport, чтобы аннотировать метод Dll, который вы хотите вызвать в неуправляемом коде.

Еще одна вещь, которая не очевидна из вашего исходного кода, - это действительный метод C. Правильно ли вы объявили его как интерфейс экспорта API с помощью __declspec (dllexport)? и если вы компилируете/кодируете его в среде С++, тогда вы должны также включить extern "C" в начале, чтобы убедиться, что интерфейс api отображается в DLL правильно, используя C-ссылку (соглашение об именах), чтобы предотвратить украшение имен С++ компилятор.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню