首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >MATLAB因调用库而崩溃(C++ .h文件和FORTRAN .dll)

MATLAB因调用库而崩溃(C++ .h文件和FORTRAN .dll)
EN

Stack Overflow用户
提问于 2019-01-22 08:29:00
回答 1查看 508关注 0票数 3

我试图在MATLAB中包含一个基于Fortran的外部DLL (用Intel Fortran编译器编译)。由于它是外部的,所以我不能对DLL的运行时库进行任何调整。目前,我在C++中编写了一个附带的头文件,以便能够调用DLL。使用loadlibrary,库被加载到MATLAB (没有错误-一个警告),然而,当使用calllib MATLAB崩溃时,不会提供错误。

我认为以下几点之一可能是造成这种情况的原因之一,但由于我对DLL的使用(特别是在C++中的编码)缺乏经验,我自己还没有发现错误。

  • 还有一个.lib文件是我从供应商那里得到的,但是我还没有将它合并到MATLAB文件或C++头文件中。
  • FILEAFILEB变量是两个输入到DLL的文本文件的路径,我认为我可能没有将它们正确地合并到C++中。
  • mHeader文件(MATLAB头文件)中,只在注释部分而不是编码部分中提到stdcall

C++和我的MATLAB脚本中的头文件代码如下所示:

代码语言:javascript
复制
#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):

代码语言:javascript
复制
%% 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);

提前感谢您的帮助!

EN

回答 1

Stack Overflow用户

发布于 2019-01-22 17:05:33

我认为您的问题是将空指针传递到FORTRAN函数,然后FORTRAN函数将尝试写入非法地址。您需要首先为输出分配内存,并将指向该内存的指针传递给您的函数。就像这样:

代码语言:javascript
复制
% Input to model
FILEA       = 'PATH\FILEA.txt';
FILEB       = 'PATH\FILEB.txt';
IDTask      = 1;
% Determine pointers
lpnErrorCode    = libpointer('int32Ptr',0); % !!! You need to know the size of these outputs!
lpErrorCode     = libpointer('int32Ptr',0);
lpProps         = libpointer('doublePtr',zeros(10,1)); 
lpOut1          = libpointer('doublePtr',zeros(4,1));
lpOut2          = libpointer('doublePtr',zeros(8,1));
lpOut3          = libpointer('doublePtr',zeros(2,1));     
lpOut4          = libpointer('doublePtr',zeros(5,1));
lpOut5          = libpointer('doublePtr',zeros(7,1));      

% LoadLibrary
[notfound, warnings] = loadlibrary('MYMODEL.dll','MYMODEL.h' ,'mfilename', 'mHeader');
% Call DLL
calllib('MYMODEL', 'MYFUN', [uint8(FILEA),0], [uint8(FILEB),0], ...
        IDTask, lpnErrorCode, lpErrorCode, lpProps, lpOut1, ...
        lpOut2, lpOut3, lpOut4, lpOut5);
% Get output values
nErrorCode = lpnErrorCode.Value;
clear lpnErrorCode
ErrorCode = lpErrorCode.Value;
clear lpErrorCode
% ... etc.

对于每个输出,我使用zeros函数创建数据。前两个是标量值(一个数据元素),另两个是不同大小的数组。我不知道您的FORTRAN函数在那里期望什么,所以我只是做了一些大小。请检查您的函数,看看每个指针应该指向的内存大小。

请注意,我还更改了将输入数据传递给函数的方式。MATLAB应自动将数据转换为正确的类型。[uint8(FILEA),0]从MATLAB char数组FILEA创建一个以零结尾的c样式字符串.在C中,字符串必须以零结尾。我不知道FORTRAN如何确定字符串的长度,我猜想它是相同的,因为函数使用"C“接口。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54304095

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档