неуправляемое / управляемое взаимодействие - проблема с передачей int [] - PullRequest
3 голосов
/ 31 января 2009

Я работаю над своей докторской диссертацией по химии, и по этой причине мне нужно написать программное приложение, которое поможет мне с визуализацией образцов под микроскопом. Этот микроскоп оснащен нанопозиционным столиком x-y-z. Этап контролируется с помощью неуправляемой библиотеки DLL, написанной на VC ++ производителем оборудования. Я мог бы предоставить вам более подробную информацию о необходимых, но позвольте мне начать с этого;

Один из методов в dll позволяет мне прочитать настройки для оси движения:

C ++ синтаксис:

BOOL E7XX_qSVO (int ID, const char* szAxes, BOOL* pbValueArray) 

Где BOOL равно int 0 или 1 в соответствии с соглашением.

Оболочка My C # содержит:

[DllImport("E7XX_GCS_DLL.dll", EntryPoint = "E7XX_qSVO")]   
public static extern int qSVO(int iId, string sAxes, int []iValArray);

Мне кажется, это правильно. Однако, когда я пытаюсь сделать что-то подобное в моем основном приложении (запросить оси 1,2 и 3):

Int32 [] _iValues = new Int32[3];
E7XXController.qSVO(m_iControllerID, "123", _iValues);

Я последовательно получаю массив, подобный этому:

{6, 0, 10}, а я должен получить {0, 0, 0} в соответствии с отображением на самом устройстве. Дополнительная функция:

BOOL E7XX_SVO (int ID, const char* szAxes, const BOOL* pbValueArray), чтобы установить те же биты состояния на сцене, также не работают ...

Другие команды в dll работают отлично. Я могу передавать строки и удваивается без проблем, но не типа BOOL ...

Ребята, вы понимаете, что может быть не так?

Ответы [ 4 ]

1 голос
/ 01 февраля 2009

Вы пытались указать атрибут MarshalAs, например :-

[DllImport("E7XX_GCS_DLL.dll", EntryPoint = "E7XX_qSVO")]   
public static extern int qSVO(int iId, 
                              [MarshalAs(UnmanagedType.AnsiBStr)]string sAxes, 
                              [MarshalAs(UnmanagedType.LPArray)]int[] iValArray);

Кроме того, вы пытались буквально передать строку sAxes в виде массива символов, например ::-

[DllImport("E7XX_GCS_DLL.dll", EntryPoint = "E7XX_qSVO")]   
public static extern int qSVO(int iId, 
                              [MarshalAs(UnmanagedType.LPArray)]char[] sAxes, 
                              [MarshalAs(UnmanagedType.LPArray)]int[] iValArray);

Я обнаружил, что с взаимодействием вам часто приходится экспериментировать, чтобы заставить его работать, поэтому пробуйте разные комбинации, проверяйте различные члены перечисления UnmanagedType, а также играйте с предложениями других людей. Однако, пожалуйста, попробуйте два вышеупомянутых метода и дайте мне знать, помогают ли они сортировать это!

1 голос
/ 01 февраля 2009

BOOL в C ++ на самом деле является «int», поэтому убедитесь, что вы используете System.Int32, а не System.Boolean. В качестве альтернативы это может быть использование типов данных COM, т. Е. VARIANT_BOOL, в этом случае вам необходим System.Boolean. Вы пытались запустить средство просмотра зависимостей для подтверждения прототипа функции?

0 голосов
/ 01 февраля 2009

Документы для вашей функции говорят:

Компилятору VC ++ требуется модификатор extern "C". Объявление также должно указывать, что эти функции должны вызываться как стандартные функции Win-API. Это означает, что компилятор VC ++ должен видеть в объявлении модификатор WINAPI или __stdcall.

Соглашение о вызовах по умолчанию для DllImport: WinApi . В Windows это StdCall. Но на CE это Cdecl. Вы хотите убедиться, что используете правильное соглашение о вызовах. Возможно, вы захотите добавить в трей:

CallConvention = CallingConvention.StdCall

Также укажите наш строковый набор символов:

CharSet = CharSet.Ansi

Но это должно работать даже без них. Это довольно странно, так как ваш код выглядит правильно.

0 голосов
/ 01 февраля 2009

Это не будет прямым ответом на ваш вопрос, но приятный инструмент для легкого получения обычных вызовов Interop Win32 использует Pinvoke.net. Даже есть плагин Visual Studio.

http://www.pinvoke.net/index.aspx

...