再会。抱歉,我的问题的定义可能不太容易理解,而且可能存在一些不准确之处——我刚刚开始尝试自己编程。不过,我会尽力把一切解释清楚。
我有用 Fortran 编写的数学 DLL。
例如,有一个函数。此函数用于将日志文件的名称解析到 dll 中以观察计算。
integer function initLog(
* int_parameter,
* char_parameter,
* char_parameter_length,
* )
*bind(C, name = "initLog");
use, intrinsic :: ISO_C_BINDING;
!DEC$ATTRIBUTES DLLEXPORT::initLog
integer(C_INT), value :: parameter;
character(C_CHAR), intent(in) :: char_parameter(char_parameter_length);
integer(C_INT), value :: char_parameter_length;
...
some_other_variable = char_parameter(1:1)(1:char_parameter_length);
end function;
通常我使用 MATLAB 来处理 dll,因此,必须使用 .mex 文件直接从 MATLAB 调用我的函数。在 .mex 文件中,我有一些用 C 语言编写的接口代码,提供 MATLAB 和 dll 之间的接口。例如,提到的函数的 C 接口是:
int doSmth(const int int_parameter,
const char* char_parameter,
const int char_parameter_length,);
然后我使用 loadLibrary 和 GetProcAddress 来获取函数。这很好用。
但是,现在我需要在 Fortran 中创建将使用我的 dll 的 .exe 测试文件。因此,我必须通过将我的 dll 链接到导入的 .lib 库来将其链接到 exe。此可执行文件的另一个选项是通过命令行将日志文件的名称作为参数。因此,首先我尝试仅从 exe 文件中传递日志文件文件名,如下所示:
program test
use dll_name;
use ifport;
implicit none;
...
integer :: log_init_status;
...
log_init_status = init_log(2, 'logfile.log', len('logfile.log'));
...
end program
这在发布时工作正常,但在调试中返回“严重(664):超出范围:子字符串结束位置'11'大于字符串长度'1'”错误。但是一开始我并没有发现这个错误并继续编写代码。这就是我现在得到的:
program test
use dll_name;
use ifport;
use ISO_C_BINDING;
implicit none;
...
character*255 :: log_flag_char;
integer(C_INT) :: log_flag;
character*255 :: filename;
character(C_CHAR) :: log_filename;
integer(C_INT) :: log_filename_length;
....
call getarg(5, log_flag_char);
read(log_flag_char, *) log_flag;
call getarg(6, log_filename);
log_filename_length = len(log_filename);
log_init_status = analyticsLogInit(log_flag, log_filename, log_filename_length);
...
end program
这很好用,但只占用了 log_filename 的第一个字符(“C:\abcd\logfile.log”转换为“C”)。如果我改变
字符(C_CHAR)::日志文件名;
至
字符(C_CHAR)::日志文件名(255);
,我遇到了 2 个问题:首先,我的 log_filename 的长度等于 255(尽管可以通过修剪来修复),其次 - 也是主要的 - 我再次得到“严重(664):超出范围:子字符串结束位置'255' 大于字符串长度 '1'”。
如果我改变
log_init_status = analyticsLogInit(log_flag, log_filename, log_filename_length);
至
log_init_status = analyticsLogInit(log_flag, C_LOC(log_filename), log_filename_length);
,我得到关于虚拟参数类型的错误与实际的不同。
我自己有一种感觉,显示的 664 错误来自 dll 中的这一行:
some_other_variable = char_parameter(1:1)(1:char_parameter_length);
. 我应该在我的exe中写类似
字符*255 :: log_filename;
并不是
字符 :: log_filename(255);
但是如何使用 (C_CHAR) 解析它?
我意识到这一切都很混乱,这一切都来自于理解的泄漏,但这几乎是我第一次认真的编程体验。