Попытка вызова функции dll из matlab, вызывающая сбой - PullRequest
2 голосов
/ 25 апреля 2011

Я пытаюсь использовать стороннюю внешнюю DLL (от usbmicro) в MATLAB, но она продолжает сбой MATLAB.Это из документации, указывающей синтаксис вызова функции из программы на Си:

int USBm_About( char *about );

Я пробовал этот скрипт MATLAB (да, это очень глупо, я нуб MATLAB):

>> loadlibrary('USBm.dll','USBmAPI.h')
>> libfunctions('USBm')
>> s='sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss';
>> st=strcat(s,s,s,s);
>> vp = libpointer('voidPtr',[int8(st) 0]);
>> result=calllib('USBm','USBm_About',vp)

и этот:

>> loadlibrary('USBm.dll','USBmAPI.h')
>> libfunctions('USBm')
>> s='sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss';
>> st=strcat(s,s,s,s);
>> vp=libpointer('cstring',st);
>> result=calllib('USBm','USBm_About',vp)

В обоих случаях вызов calllib() вызывает сбой MATLAB с ошибкой сегментации.

Версия MATLAB - 7.10;ОС Windows Vista.


Обновление:

Вот скриншот libfunctionsview USBm: screenshot

Вот файл заголовка:

#ifndef FILE_USBmAPI_h
#define FILE_USBmAPI_h


// Prototypes for this DLL.
// These are the API functions available to the .dll user.


// Discovery routine
extern "C" __declspec(dllexport) int USBm_FindDevices(void);

// Return info about devices
extern "C" __declspec(dllexport) int USBm_NumberOfDevices(void);
extern "C" __declspec(dllexport) int USBm_DeviceValid(unsigned char);
extern "C" __declspec(dllexport) int USBm_DeviceVID(unsigned char);
extern "C" __declspec(dllexport) int USBm_DevicePID(unsigned char);
extern "C" __declspec(dllexport) int USBm_DeviceDID(unsigned char);
extern "C" __declspec(dllexport) int USBm_DeviceFirmwareVer(unsigned char);
extern "C" __declspec(dllexport) int USBm_DeviceMfr(unsigned char, char *);
extern "C" __declspec(dllexport) int USBm_DeviceProd(unsigned char, char *);
extern "C" __declspec(dllexport) int USBm_DeviceSer(unsigned char, char *);

// General USBmicro U4xx device access
extern "C" __declspec(dllexport) int USBm_ReadDevice(unsigned char, unsigned char *);
extern "C" __declspec(dllexport) int USBm_SetReadTimeout(unsigned int);
extern "C" __declspec(dllexport) int USBm_WriteDevice(unsigned char, unsigned char *);
extern "C" __declspec(dllexport) int USBm_CloseDevice(unsigned char);

// DLL string info access
extern "C" __declspec(dllexport) int USBm_RecentError(char *);
extern "C" __declspec(dllexport) int USBm_ClearRecentError(void);
extern "C" __declspec(dllexport) int USBm_DebugString(char *);
extern "C" __declspec(dllexport) int USBm_Copyright(char *);
extern "C" __declspec(dllexport) int USBm_About(char *);
extern "C" __declspec(dllexport) int USBm_Version(char *);



// General U4x1 device functions
// -----------------------------

// Port initialization
extern "C" __declspec(dllexport) int USBm_InitPorts(unsigned char);
extern "C" __declspec(dllexport) int USBm_InitPortsU401(unsigned char);
extern "C" __declspec(dllexport) int USBm_InitPortsU421(unsigned char);
extern "C" __declspec(dllexport) int USBm_InitPortsU451(unsigned char);

// Port/bit reading and writing
extern "C" __declspec(dllexport) int USBm_WriteA(unsigned char, unsigned char);
extern "C" __declspec(dllexport) int USBm_WriteB(unsigned char, unsigned char);
extern "C" __declspec(dllexport) int USBm_WriteABit(unsigned char, unsigned char, unsigned char);
extern "C" __declspec(dllexport) int USBm_WriteBBit(unsigned char, unsigned char, unsigned char);
extern "C" __declspec(dllexport) int USBm_ReadA(unsigned char, unsigned char *);
extern "C" __declspec(dllexport) int USBm_ReadB(unsigned char, unsigned char *);
extern "C" __declspec(dllexport) int USBm_SetBit(unsigned char, unsigned char);
extern "C" __declspec(dllexport) int USBm_ResetBit(unsigned char, unsigned char);

// Port direction
extern "C" __declspec(dllexport) int USBm_DirectionA(unsigned char, unsigned char, unsigned char);
extern "C" __declspec(dllexport) int USBm_DirectionAOut(unsigned char);
extern "C" __declspec(dllexport) int USBm_DirectionAIn(unsigned char);
extern "C" __declspec(dllexport) int USBm_DirectionAInPullup(unsigned char);
extern "C" __declspec(dllexport) int USBm_DirectionB(unsigned char, unsigned char, unsigned char);
extern "C" __declspec(dllexport) int USBm_DirectionBOut(unsigned char);
extern "C" __declspec(dllexport) int USBm_DirectionBIn(unsigned char);
extern "C" __declspec(dllexport) int USBm_DirectionBInPullup(unsigned char);

// Strobbing a byte of data
extern "C" __declspec(dllexport) int USBm_StrobeWrite(unsigned char, unsigned char, unsigned char, unsigned char);
extern "C" __declspec(dllexport) int USBm_StrobeRead(unsigned char, unsigned char *, unsigned char, unsigned char);
extern "C" __declspec(dllexport) int USBm_StrobeWrite2(unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char);
extern "C" __declspec(dllexport) int USBm_StrobeRead2(unsigned char, unsigned char *, unsigned char, unsigned char, unsigned char, unsigned char);
extern "C" __declspec(dllexport) int USBm_StrobeWrites(unsigned char, unsigned char *, unsigned char *);
extern "C" __declspec(dllexport) int USBm_StrobeReads(unsigned char, unsigned char *, unsigned char *);

// Reading pin-change latches
extern "C" __declspec(dllexport) int USBm_ReadLatches(unsigned char, unsigned char *);

// LCD routines
extern "C" __declspec(dllexport) int USBm_InitLCD(unsigned char, unsigned char, unsigned char);
extern "C" __declspec(dllexport) int USBm_LCDCmd(unsigned char, unsigned char);
extern "C" __declspec(dllexport) int USBm_LCDData(unsigned char, unsigned char);

// SPI routines
extern "C" __declspec(dllexport) int USBm_InitSPI(unsigned char, unsigned char);
extern "C" __declspec(dllexport) int USBm_SPIMaster(unsigned char, unsigned char *, unsigned char *);
extern "C" __declspec(dllexport) int USBm_SPISlaveWrite(unsigned char, unsigned char, unsigned char *);
extern "C" __declspec(dllexport) int USBm_SPISlaveRead(unsigned char, unsigned char *, unsigned char *);

// 2-wire routines
extern "C" __declspec(dllexport) int USBm_Wire2Control(unsigned char, unsigned char *);
extern "C" __declspec(dllexport) int USBm_Wire2Data(unsigned char, unsigned char *);

// Stepper routine
extern "C" __declspec(dllexport) int USBm_Stepper(unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char);

// 1-wire routines
extern "C" __declspec(dllexport) int USBm_Reset1Wire(unsigned char, unsigned char *);
extern "C" __declspec(dllexport) int USBm_Write1Wire(unsigned char, unsigned char);
extern "C" __declspec(dllexport) int USBm_Read1Wire(unsigned char, unsigned char *);
extern "C" __declspec(dllexport) int USBm_Write1WireBit(unsigned char, unsigned char);
extern "C" __declspec(dllexport) int USBm_Read1WireBit(unsigned char, unsigned char *);




#endif // multiple inclusion prevention

// End of file
//---------------------------------------------------------------------------

Обновление:

Я попытался изменить эту строку:

extern "C" __declspec(dllexport) int USBm_About(char *);

на эту:

extern "C" __declspec(dllimport) int USBm_About(char *);

в заголовочном файле и затем перезапустить MATLAB,Я снова запустил свой код, и MATLAB все еще вылетает.

Ответы [ 2 ]

2 голосов
/ 19 октября 2011

Я скачал библиотеку DLL с веб-сайта USBmicro и попытался использовать ее , позвонив по номеру loadlibrary(). К сожалению, это привело к сбою моего сеанса MATLAB, как вы сказали ..

После некоторого исследования я пришел к выводу, что способ, которым эта DLL предоставляет свои функции, не совместим с соглашением о вызовах, которого ожидает MATLAB (cdecl против stdcall).

Вот как я исправил заголовочный файл:

#ifndef FILE_USBmAPI_h
#define FILE_USBmAPI_h

#ifdef __cplusplus
extern "C" {
#endif

// ...
int __stdcall USBm_About(char *);
int __stdcall USBm_Version(char *);
// ...

#ifdef __cplusplus
}
#endif

#endif

Теперь вы можете вызывать любую из экспортируемых функций. Пример:

%# load library and see exported functions signatures
if ~libisloaded('USBm')
    loadlibrary('USBm.dll','USBmAPI.h')
    libfunctions('USBm','-full')
end

%# call the function: `int USBm_About(char *)`
str = repmat(' ',1,100);                           %# allocate buffer
pStr = libpointer('stringPtr',str);                %# pointer to string
[num str2] = calllib('USBm','USBm_About',pStr)
clear pStr

%# unload library
unloadlibrary USBm

Обратите внимание на сигнатуру функции, которую нам дает MATLAB:

[int32, cstring] USBm_About(cstring)

Интересно, что у нее есть дополнительный выходной аргумент для этой функции. Причина в том, что MATLAB на самом деле не поддерживает передачу по ссылке, хотя вы можете создавать аргументы MATLAB, которые совместимы с указателями C.

Таким образом, если функция C возвращает данные во входных аргументах, переданных по ссылке, MATLAB создаст дополнительные выходные аргументы для возврата этих значений (и любых входных аргументов, заканчивающихся на Ptr или PtrPtr).

Теперь, хотя входной аргумент pStr напоминает указатель на тип char, он не является истинным, поскольку не содержит адреса массива символов MATLAB str. Когда функция выполняется, она возвращает правильный результат, но не изменяет значение в str (ни в этом случае pStr для этого не имеет значения).

Вывод, который я получил, был:

>> num
num =
     0

>> str2
str2 =
 USBm.dll by USBmicro L.L.C. (www.usbmicro.com). Supports: U401, U421
0 голосов
/ 25 апреля 2011

Это может быть стандартная проблема, которая должна иметь ваш включаемый файл

extern "C" __declspec(dllexport)

когда вы создаете .dll, но Matlab (или какой-либо другой проект, использующий ваш .dll) должен иметь:

extern "C" __declspec(dllimport)

когда вы включаете его.

Вот почему у людей обычно есть следующий макрос:

#ifdef USBMAPIEXPORTS 
#define USBMAPIDECLSPEC __declspec(dllexport)
#else
#define USBMAPIDECLSPEC __declspec(dllimport)
#endif

и затем о ваших функциях в заголовке вы пишете:

extern "C" USBMAPIDECLSPEC int USBm_FindDevices(void);    

и вам нужно определить USBMAPIEXPORTS при сборке .dll (но не при использовании в Matlab.)

Обратите внимание, что это не проблема с Matlab. Это стандартный способ использования .dll. Вы пробовали это?

...