Функция FORTRAN, возвращающая массив, вызывает segfault (вызов из C++)
В основном, вот моя проблема. Я вызываю чужие функции FORTRAN из моего кода C++, и это доставляет мне головную боль. Некоторый код:
function c_error_message()
character(len = 255) :: c_error_message
errmsg(1:9) = 'ERROR MSG'
return
end
Это функция Фортрана. Мой первый вопрос: есть ли там что-нибудь, что могло бы вызвать segfault?
Если нет, то второе: что это возвращает? Указатель? Я пытаюсь вызвать это с помощью следующего оператора C:
char *e = c_error_message_();
Это вызывает segfault.
c_error_message();
Это тоже вызывает сегфо
Ранее я объявил c_error_message_() со следующим кодом:
extern"C" {
char* c_error_message_();
}
Будет ли объявление функции с типом возврата, отличным от фактического типа возврата, вызвать segfault?
Я в недоумении. Спасибо за любые ответы.
3 ответа
Вот метод, который работает. Когда я попытался использовать привязку ISO C с функцией, возвращающей строку, компилятор возразил. Так что если вместо этого вы используете аргумент подпрограммы:
subroutine fort_err_message (c_error_message) bind (C, name="fort_err_message")
use iso_c_binding, only: C_CHAR, C_NULL_CHAR
character (len=1, kind=C_CHAR), dimension (255), intent (out) :: c_error_message
character (len=255, kind=C_CHAR) :: string
integer :: i
string = 'ERROR MSG' // C_NULL_CHAR
do i=1, 255
c_error_message (i) = string (i:i)
end do
return
end subroutine fort_err_message
Фортран немного неловкий, потому что технически C-строка представляет собой одномерный массив символов.
И пример кода C для демонстрации, что это работает:
#include <stdio.h>
void fort_err_message ( char chars [255] );
int main ( void ) {
char chars [255];
fort_err_message ( chars );
printf ( "%s\n", chars );
return 0;
}
Поскольку вторая строка объявляет имя, совпадающее с именем функции, она объявляет тип возвращаемого значения функции, а именно строку символов масштабатора из 255 символов. Но в теории это не говорит нам о внутреннем API - это компилятор. Я не знаю, откуда взято "errmsg" - оно должно быть объявлено в другом месте - возможно, глобальной переменной, как предложено Майклом Андерсоном. Или, возможно, это ошибка, и строка должна быть c_error_message = "ОШИБКА MSG". (Нет необходимости указывать диапазон подстроки - остальная часть строки будет заполнена пробелами.) IMO, лучший подход к вызову Fortran из C (или наоборот) заключается в использовании ISO C Связывание, которое заставит компилятор Фортрана использовать C-совместимый интерфейс. Я не сделал функцию, возвращающую строку, но сделал строки в качестве аргументов.
Функции FORTRAN возвращают значение, присвоенное имени функции. Возвращаемый тип определяется в определении функции, и в этом случае он возвращает строку символов длиной 255 символов. Я думаю, что несоответствие типов является причиной того, что вы segfaulting. Так какой тип C вы должны использовать? Я не знаю.
Я нашел это Используя C с страницей FORTRAN, и автор настоятельно рекомендует использовать подпрограммы FORTRAN и вызывать их как функции C, возвращающие тип void.