У меня есть метод, определенный в неуправляемой DLL:
int foo(somestruct * vector, int size)
Как я могу вызвать этот метод из С#? По сути, я хочу завершить следующий фрагмент кода:
[StructLayout(LayoutKind.Sequential), Serializable]
public struct somestruct
{
//Whatever.
};
[DLLImport("some.dll")]
public static extern int foo( ???? );
Спасибо.
Это намного проще, чем вы думаете.
[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 и передать указатель на управляемую копию.
Посмотрите атрибут 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
Да, насколько я знаю, вы должны маршевать этот массив вручную, используя IntPtr
. Не так давно был вопрос, посмотрите здесь. Другой подход заключается в том, чтобы переписать собственный код в управляемый С++ или создать С++-оболочку, которая вызывает DLL для вас.
LPArray
должен быть правильным.
Правильно ли определено определение somestruct
? Является ли ваш C int
32 бита, или у вас, возможно, есть несоответствие?
Возможно, опубликуйте определение, которое вы попробовали и в вопросе, это может прояснить ситуацию.
.NET interop не имеет проблем со структурой, а также с неуправляемым массивом. Вы можете определить struct в С# и рассказать его в макет последовательно через пользовательский атрибут, чтобы он мог сопоставить вам структуру C. Для массива вы можете использовать LPArray или даже IntPtr и самостоятельно его сортировать. Вам нужно будет использовать атрибут DllImport, чтобы аннотировать метод Dll, который вы хотите вызвать в неуправляемом коде.
Еще одна вещь, которая не очевидна из вашего исходного кода, - это действительный метод C. Правильно ли вы объявили его как интерфейс экспорта API с помощью __declspec (dllexport)
?
и если вы компилируете/кодируете его в среде С++, тогда вы должны также включить extern "C" в начале, чтобы убедиться, что интерфейс api отображается в DLL правильно, используя C-ссылку (соглашение об именах), чтобы предотвратить украшение имен С++ компилятор.
DllImport
здесь не является проблемой.