0

再会。抱歉,我的问题的定义可能不太容易理解,而且可能存在一些不准确之处——我刚刚开始尝试自己编程。不过,我会尽力把一切解释清楚。

我有用 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) 解析它?

我意识到这一切都很混乱,这一切都来自于理解的泄漏,但这几乎是我第一次认真的编程体验。

4

1 回答 1

2

我只看了你的问题,但要注意的一件事character是声明变量或命名常量的方式。您可以提供两个类型参数:长度和种类。如果在声明中不使用相应的关键字,则第一个参数指定长度,第二个参数(如果存在)指定种类。
因此,如果要声明长度为 255 和 kind 的字符变量C_CHAR,可以通过以下任何一种方式进行:

character(len=255, kind=C_CHAR) :: log_filename
character(255, kind=C_CHAR)     :: log_filename
character(255, C_CHAR)          :: log_filename
character(kind=C_CHAR, len=255) :: log_filename
character(kind=C_CHAR)          :: log_filename*255

另一方面,以下语法(这是您使用的语法)声明了一个character长度变量C_CHAR,无论它可能是什么值。

character(C_CHAR) :: log_filename

哦,下一个语法声明了一个包含 255 个元素的数组,每个元素都是一个长度为的字符变量C_CHAR

character(C_CHAR) :: log_filename(255)

所以结论是,应该花一些时间来研究在 fortran 中声明字符实体的特性。

于 2012-02-24T23:31:50.343 回答