2010-03-25 3 views
2

В принципе, вот моя проблема. Я вызываю чужие функции FORTRAN из моего кода на C++, и это дает мне головные боли. Некоторый код:Функция FORTRAN, возвращающая массив, вызывает segfault (вызов из C++)

function c_error_message() 
character(len = 255) :: c_error_message 
errmsg(1:9) = 'ERROR MSG' 
return 
end 

Это функция FORTRAN. Мой первый вопрос: есть ли что-нибудь, что может вызвать segfault?

Если нет, то второй: что это значит? Указатель? Я пытаюсь вызвать его со следующим утверждением: C:

char *e = c_error_message_(); 

Это вызывает Segfault.

c_error_message(); 

Это также вызывает segfault.

Я объявил c_error_message_() ранее на со следующим кодом:

extern"C" { 
    char* c_error_message_(); 
} 

бы объявление функции с другим типом возвращаемого значения, чем фактический тип возвращаемого вызвать Segfault?

Я в затруднении. Спасибо за любые ответы.

ответ

2

Это метод, который работает. Когда я попытался использовать привязку 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-строка представляет собой 1D массив символов.

И пример 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; 

} 
+0

Работал отлично. Благодаря тонну! –

+0

Можете ли вы рассказать о том, каким был корень (под капотом) причины segfault? –

1

Поскольку вторая строка объявляет имя, которое совпадает с именем функции, оно объявляет тип возвращаемой функции, а именно строку масштабирования символов длиной 255 символов. Но теоретически это не говорит нам о внутреннем API - это компилятор. Я не знаю, откуда происходит «errmsg» - он должен быть объявлен в другом месте - возможно, глобальная переменная, предложенная Майклом Андерсоном. Или, может быть, это ошибка, и строка должна быть c_error_message = «ERROR MSG». (Нет необходимости указывать диапазон подстроки - остальная часть строки будет заполнена пробелами.) IMO, лучший подход к вызову Fortran с C (или наоборот) - использовать ISO C Binding, что заставит компилятор Fortran использовать C-совместимый интерфейс. Я не выполнял функцию, возвращающую строку, но делал строки как аргументы.

0

Функции FORTRAN возвращают значение, присвоенное имени функции. Возвращаемый тип задается определением функции, и в этом случае он возвращает строку символов длиной 255 символов. Я думаю, что несоответствие типа - это то, почему вы сталкиваетесь. Итак, какой тип C вы должны использовать? Я не знаю.

Я нашел эту страницу Using C with FORTRAN, и автор настоятельно рекомендует использовать подпрограммы FORTRAN и называть их функциями C, возвращающими тип void.

Адрес F95 quick reference.

+1

«Использование для C с FORTRAN страницы» с 2001 года является устаревшим и имеет неверную информацию. Например, утверждение, что только int/INTEGER, float/REAL и double/DOUBLE может быть надежно изменено, перестает быть истинным.В прошлом языки подключения были специфичны для компилятора и платформы. С привязкой ISO C к Fortran 2003 Fortran и языки с внутренним интерфейсом C можно смешивать стандартным образом, не являющимся компилятором и платформой. –

+0

+1 Интересно. Я не знал этого. Я не писал FORTRAN в течение долгого времени, и вы, очевидно, продолжали! – Fred

Смежные вопросы