使用 C++ 调用 Fortran 的 SDL:作用域和初始化程序错误
SDL with C++ calling Fortran: Scope and Initializer error
我想从旧的 Fortran 程序调用计算,但在 C++-SDL 例程中显示结果。
现在我已经阅读了所有与此相关的问题,但是在遵循所有规定之后我仍然遇到编译器错误。
相关代码片段如下:
SDL_wrapper.h:
extern "C++" void __stdcall callSomeFortran_();
SDL_wrapper.cpp:
#include "/usr/include/SDL/SDL.h"
#include "/usr/include/SDL/SDL_image.h"
#include <stdio.h>
#include "SDL_wrapper.h"
using namespace std;
int main(int argc, char *argv[])
{
callSomeFortran();
SDL_Surface *screen;
(...)
fortranFunctions.f90:
subroutine callSomeFortran() bind(C)
use iso_c_binding
implicit none
write(*,*) 'Were in Fortran!'
end subroutine callSomeFortran
现在当我不在 main 中调用 callSomeFortran()
时,我可以用
完美编译
makefile
FLAGS = -lSDL -lstdc++
fortranFunctions: fortranFunctions.o wrapper.o
gfortran -o fortranFunctions wrapper.o fortranFunctions.o $(FLAGS)
fortranFunctions.o: fortranFunctions.f90
gfortran -c fortranFunctions.f90 -ffree-line-length-none -o fortranFunctions.o
但是因为我当然想调用该函数,所以我包含了它并得到了以下错误:
In file included from SDL_wrapper.cpp:5:0:
SDL_wrapper.h:1:29: error: expected initializer before ‘callSomeFortran_’
SDL_wrapper.cpp: In function ‘int main(int, char**)’:
SDL_wrapper.cpp:20:20: error: ‘callSomeFortran’ was not declared in this scope
我真的不明白。从我研究过的所有以前的帖子来看,这应该有效。此外,我已经有多年的编码经验,不知道范围应该有问题的地方。
我是不是遗漏了什么明显的东西?
extern "C++" void __stdcall callSomeFortran_();
错了。
您在 Fortran 中将其声明为
callSomeFortran() bind(C)
bind(C)
意味着(不仅)不会附加尾随下划线,您也不应该在 C++ 中附加它。最好明确地写成 bind(C,name="callSomeFortran")
我没有看到 __stdcall
的任何理由,我认为您使用的是默认调用约定。
应该是extern "C"{}
,不是"C++"
。您希望它具有 C 链接。
extern "C"
和 bind(C)
做的事情非常相似。强制过程遵循简单的 C 调用约定。这意味着对于 Fortran 和 C++,过程的符号将是函数的名称,没有任何变化。对于 Fortran,它还意味着所有变量都将使用指向它们的指针传递,除非声明为 value
.
如果没有 bind(C)
,符号的名称将附加 _
,但此行为因编译器而异。另外,对于模块程序,它更复杂。
如果没有extern "C"
,符号的名称会很复杂,规则也不规范。
我想从旧的 Fortran 程序调用计算,但在 C++-SDL 例程中显示结果。
现在我已经阅读了所有与此相关的问题,但是在遵循所有规定之后我仍然遇到编译器错误。
相关代码片段如下:
SDL_wrapper.h:
extern "C++" void __stdcall callSomeFortran_();
SDL_wrapper.cpp:
#include "/usr/include/SDL/SDL.h"
#include "/usr/include/SDL/SDL_image.h"
#include <stdio.h>
#include "SDL_wrapper.h"
using namespace std;
int main(int argc, char *argv[])
{
callSomeFortran();
SDL_Surface *screen;
(...)
fortranFunctions.f90:
subroutine callSomeFortran() bind(C)
use iso_c_binding
implicit none
write(*,*) 'Were in Fortran!'
end subroutine callSomeFortran
现在当我不在 main 中调用 callSomeFortran()
时,我可以用
makefile
FLAGS = -lSDL -lstdc++
fortranFunctions: fortranFunctions.o wrapper.o
gfortran -o fortranFunctions wrapper.o fortranFunctions.o $(FLAGS)
fortranFunctions.o: fortranFunctions.f90
gfortran -c fortranFunctions.f90 -ffree-line-length-none -o fortranFunctions.o
但是因为我当然想调用该函数,所以我包含了它并得到了以下错误:
In file included from SDL_wrapper.cpp:5:0:
SDL_wrapper.h:1:29: error: expected initializer before ‘callSomeFortran_’
SDL_wrapper.cpp: In function ‘int main(int, char**)’:
SDL_wrapper.cpp:20:20: error: ‘callSomeFortran’ was not declared in this scope
我真的不明白。从我研究过的所有以前的帖子来看,这应该有效。此外,我已经有多年的编码经验,不知道范围应该有问题的地方。
我是不是遗漏了什么明显的东西?
extern "C++" void __stdcall callSomeFortran_();
错了。
您在 Fortran 中将其声明为
callSomeFortran() bind(C)
bind(C)
意味着(不仅)不会附加尾随下划线,您也不应该在 C++ 中附加它。最好明确地写成 bind(C,name="callSomeFortran")
我没有看到
__stdcall
的任何理由,我认为您使用的是默认调用约定。应该是
extern "C"{}
,不是"C++"
。您希望它具有 C 链接。
extern "C"
和 bind(C)
做的事情非常相似。强制过程遵循简单的 C 调用约定。这意味着对于 Fortran 和 C++,过程的符号将是函数的名称,没有任何变化。对于 Fortran,它还意味着所有变量都将使用指向它们的指针传递,除非声明为 value
.
如果没有 bind(C)
,符号的名称将附加 _
,但此行为因编译器而异。另外,对于模块程序,它更复杂。
如果没有extern "C"
,符号的名称会很复杂,规则也不规范。