Функция FORTRAN, возвращающая массив, вызывает segfault (вызов из C ++) - PullRequest
2 голосов
/ 25 марта 2010

В принципе, вот моя проблема. Я вызываю чужие функции 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();

Это также приводит к segfault.

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

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

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

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

Ответы [ 3 ]

2 голосов
/ 25 марта 2010

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

}
1 голос
/ 25 марта 2010

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

0 голосов
/ 25 марта 2010

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

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

Вот краткий справочник F95 .

...