2

MATLAB 内でサードパーティの外部 DLL (usbmicro から) を使用しようとしていますが、MATLAB がクラッシュし続けます。これは、C プログラム内からの関数呼び出しの構文を示すドキュメントからのものです。

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 です。OSはWindows Vistaです。


アップデート:

libfunctionsview USBm のスクリーンショットは次のとおりです。 スクリーンショット

ヘッダーファイルは次のとおりです。

#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 は依然としてクラッシュします。

4

2 に答える 2

2

USBmicroのWebサイトからDLLをダウンロードし、を呼び出して使用して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)

興味深いことに、この関数には追加の出力引数があります。その理由は、Cポインターと互換性のあるMATLAB引数を作成することはできますが、MATLABは参照による受け渡しを実際にはサポートしていないためです。

したがって、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
于 2011-10-19T08:35:09.287 に答える
0

これは、インクルードファイルに必要な標準的な問題である可能性があります

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を使用する標準的な方法です。 これを試しましたか?

于 2011-04-25T19:53:14.190 に答える