【发布时间】:2019-01-22 08:29:00
【问题描述】:
我正在尝试在 MATLAB 中包含一个基于外部 FORTRAN(使用英特尔 Fortran 编译器编译)的 DLL。由于它是外部的,我无法对 DLL 的运行时库进行任何调整。目前,我用 C++ 编写了一个随附的头文件,以便能够调用 DLL。使用 loadlibrary 库被加载到 MATLAB(没有错误 - 一个警告),但是,当使用 calllib 时,MATLAB 崩溃并且不提供错误。
我认为以下原因之一可能是造成这种情况的原因,但由于我对使用 DLL(尤其是 C++ 编码)缺乏经验,我自己还没有发现错误。
- 我还从供应商处获得了一个 .lib 文件,但我尚未将其合并到 MATLAB 文件或 C++ 头文件中。
-
FILEA和FILEB变量是输入到 DLL 的两个文本文件的路径,我想我可能没有在 C++ 中正确合并这些文件。 - 在
mHeader文件(MATLAB 头文件)中,stdcall仅在注释部分提及,而不在编码部分提及。
C++头文件的代码和我的MATLAB脚本如下所示:
#ifndef _MYMODEL
#define _MYMODEL
#ifdef __cplusplus
extern "C" {
#endif // _cplusplus
// Functions and data types defined
void __stdcall MYFUN(char FILEA[], char FILEB[], int *IDTask, int
*nErrorCode, int *ErrorCode, double *Props, double *Out1, double *Out2,
double *Out3, double *Out4, double *Out5);
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // !_MYMODEL
MATLAB (r2018b):
%% Input to model
FILEA = 'PATH\FILEA.txt';
FILEB = 'PATH\FILEB.txt';
IDTask = 1; %Multiple tasks possible in the .dll
%% Determine pointers
lpFILEA = libpointer('cstring', FILEA);
lpFILEB = libpointer('cstring', FILEB);
lpIDTask = libpointer('int32Ptr', IDTask);
lpnErrorCode = libpointer('int32Ptr');
lpErrorCode = libpointer('int32Ptr');
lpProps = libpointer('doublePtr');
lpOut1 = libpointer('doublePtr');
lpOut2 = libpointer('doublePtr');
lpOut3 = libpointer('doublePtr');
lpOut4 = libpointer('doublePtr');
lpOut5 = libpointer('doublePtr');
%% LoadLibrary
[notfound, warnings] = loadlibrary('MYMODEL.dll','MYMODEL.h' ,'mfilename', 'mHeader');
%% Call .dll
[~,~, ~, nErrorOut, ErrorCodeOut, PropsOut, Out1_, ~, ~, Out4_, Out5_] ...
= calllib('MYMODEL', 'MYFUN', lpFILEA, ...
lpFILEB, lpIDTask, lpnErrorCode, lpErrorCode, lpProps, lpOut1, ...
lpOut2, lpOut3, lpOut4, lpOut5);
提前感谢您的帮助!
【问题讨论】:
-
when using calllib MATLAB crashes and does provide an error.-> 也很高兴在这里看到错误输出。 -
您可以做的是将调试器(例如,使用
Attach to the Process从 Visual Studio 连接到 Matlab 进程)。并在 Matlab 进入你的calllib函数之前设置一个断点。然后您可以进入代码,前提是dll具有调试符号,即假设它是在调试模式而不是发布模式下编译的。我记得 5 到 6 年前为一个用 C 语言编写的 mex 文件执行此操作,该文件是从 Matlab 调用的。我不能 100% 确定,dll文件是否也可以这样做。 -
如果使用调试器看起来很麻烦(或者不适用于 dll 文件),那么您还可以做的是,如果您有源代码Fortran 代码,将调试行放在 matlab 进入该 dll 文件的 fortran 代码的开头。这样,您至少会知道对 dll 的调用可以正常工作,并且错误发生在 dll 文件中的某处。然后,您可以使用跟踪线
walk the code来定位,直到代码正常工作为止。跟踪线可以进入文本文件。我知道,这看起来很原始,但是当没有其他方法起作用时,就是这样。 -
你能从一个fortran程序中毫无问题地链接和调用fortran库的成员函数吗?
-
@newkid 不,我不知道。我会就此联系 .dll 供应商,这样我就可以解决这个问题(也许可以在另一个问题中解决......)