Добрый день. Извините, возможно, не очень понятное определение моей проблемы и, возможно, некоторые неточности - я только начинаю попробовать себя в программировании. Тем не менее, я постараюсь изо всех сил объяснить все просто.Совместимость символов символов C-Fortran
У меня есть математическая библиотека, написанная на Фортране.
Например, есть функция. Эта функция используется для анализа имени файла журнала в 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, чтобы получить функцию. И это прекрасно работает.
Однако теперь мне нужно создать тестовый файл .exe в Fortran, который будет использовать мою dll. Итак, мне нужно связать свою dll с exe, связав ее с библиотекой import .lib. Другой вариант для этого исполняемого файла - взять имя файла журнала через командную строку в качестве параметра. Итак, сначала я пытался передать лог файл только из файла 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) :: log_filename;
к
символ (C_CHAR) :: log_filename (255);
, я получаю 2 проблемы: во-первых, у меня есть длина моего log_filename равный 255 (может быть исправлено аккуратным, хотя), а второй - и главное - я снова получить «тяжелый (664): Out диапазона: конечная позиция подстроки '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)?
Я понимаю, что все это довольно грязно, и все это происходит из-за утечки понимания, но это мой почти первый серьезный опыт в программировании.
Благодарим за ответ. Конечно, я понимаю, что в Фортране для меня есть много дел.Тем не менее, я был уверен, что синтаксис character (C_CHAR) :: log_filename отлично работает, поскольку он работает с целыми числами и удваивает (и потому, что он был написан в прочитанной статье) – AntalOvc
Увы, смена символа (C_CHAR) на «character (kind = C_CHAR)» ничего не давал. Кроме того, теперь я не понимаю, как «some_other_variable = char_parameter (1: 1) (1: char_parameter_length);» работает, если объявлен как «символ (C_CHAR), намерение (in) :: char_parameter (char_parameter_length)»; – AntalOvc