Я пытаюсь отправить некоторые данные из кода FORTRAN (f90) в функцию C ++. Упрощенный рабочий код будет выглядеть так:
main.f90:
program test
!
integer:: ii, jj, kk
common/ijk/ ii, jj, kk
character*32 cc
ii = 2
jj = 3
kk = 4
cc = 'Example of a character string'
!
call doubleIJK(cc)
!
write(*,*) ii, jj, kk
!
end program test
и func.cpp:
#ifdef __cplusplus
extern"C" {
#endif
#include <stdio.h>
extern struct
{
int ii, jj, kk;
} ijk_;
void *__gxx_personality_v0;
int doubleijk_(char *cc, int ll)
{
cc[ll--] = '\0'; // NULL terminate the string
printf("From doubleIJK: %s\n",cc);
ijk_.ii *=2;
ijk_.jj *=2;
ijk_.kk *=2;
return(1);
}
#ifdef __cplusplus
}
#endif
и мой Makefile:
# Compilers
FORTRAN_COMPILER = ifort
CPP_COMPILER = g++
# Flags
CPP_FLAG = -c #-lstdc++
FORTRAN_FLAG = -o
# Rules:
test.exe: main.o func.o
$(FORTRAN_COMPILER) $(FORTRAN_FLAG) test.exe main.o func.o
# Objects
func.o: func.cpp
($(CPP_COMPILER) $(CPP_FLAG) func.cpp)
main.o: main.f90
($(FORTRAN_COMPILER) $(CPP_FLAG) main.f90)
========================================
Далее я хотел бы вызвать другую функцию cpp для выполнения некоторых операций с данными, которые сейчас есть в func.cpp. Упрощенная версия будет выглядеть так:
addition.cpp:
#include <iostream>
#include "addition.h"
using namespace std;
int addition (int a, int b)
{
int r;
r = a + b;
cout << r << endl;
return r;
}
addition.h:
#ifndef ADDITION_H
#define ADDITION_H
int addition (int a, int b);
#endif /* ADDITION_H */
И обновленный Makefile:
# Compilers
FORTRAN_COMPILER = ifort
CPP_COMPILER = g++
# Flags
CPP_FLAG = -c #-lstdc++
FORTRAN_FLAG = -o
# Rules:
test.exe: main.o func.o addition.o
$(FORTRAN_COMPILER) $(FORTRAN_FLAG) test.exe main.o func.o addition.o
# Objects
func.o: func.cpp
($(CPP_COMPILER) $(CPP_FLAG) func.cpp)
addition.o: addition.cpp
($(CPP_COMPILER) $(CPP_FLAG) addition.cpp)
main.o: main.f90
($(FORTRAN_COMPILER) $(CPP_FLAG) main.f90)
Я также обновляю func.cpp как:
#ifdef __cplusplus
extern"C" {
#endif
#include <stdio.h>
#include "addition.h"
extern struct
{
int ii, jj, kk;
} ijk_;
void *__gxx_personality_v0;
int doubleijk_(char *cc, int ll)
{
cc[ll--] = '\0'; // NULL terminate the string
printf("From doubleIJK: %s\n",cc);
ijk_.ii *=2;
ijk_.jj *=2;
ijk_.kk *=2;
int z;
z = addition (5,3);
return(1);
}
#ifdef __cplusplus
}
#endif
Я не смог скомпилировать код. Я не уверен, но я думаю, что-то не так с make-файлом, так как каждый раз, когда я меняю порядок объектных файлов, я получаю разные ошибки, такие как:
/tmp/cc4AuTkF.o(.text+0x50): In function `doubleijk_':
: undefined reference to `ijk_'
/tmp/cc4AuTkF.o(.text+0x58): more undefined references to `ijk_' follow
collect2: ld returned 1 exit status
make: *** [func.o] Error 1
или же
func.o(.text+0x67): In function `doubleijk_':
: undefined reference to `addition'
addition.o(.text+0x23): In function `__static_initialization_and_destruction_0(int, int)':
: undefined reference to `std::ios_base::Init::Init()'
addition.o(.text+0x28): In function `__static_initialization_and_destruction_0(int, int)':
: undefined reference to `std::ios_base::Init::~Init()'
addition.o(.text+0x6f): In function `addition(int, int)':
: undefined reference to `std::cout'
Буду признателен за любую помощь по этому вопросу.
Как и в комментариях, добавьте правильную библиотеку времени выполнения для C ++ при связывании с компилятором Fortran.
FORTRAN_FLAG = -lstdc++ -o
С GCC вы можете даже просто сделать
gfortran *.cpp *.f90 -lstdc++ -o test.exe
Вы также можете связать с компилятором C ++ и добавить библиотеки Fortran к команде link.
Заметки нет iso_c_binding
в любом месте вашего кода, даже если вы используете тег и ссылаетесь на него в заголовке. Это современный способ взаимодействия C и Fortran. Если вы хотите узнать больше о современных подходах, прочитайте тег вики-страницу.