Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
386 views
in Technique[技术] by (71.8m points)

linker - Calling C++ from Fortran (linking issue?)

I really need your help! I'm on a deadline and I'm trying to learn just enough to get some work done. It's been well over a week now that I'm dealing with what appears to be a straightforward issue but I haven't been able to successfully implement solutions online.

Long story short: I need to call C++ code from F77. I'm compiling with g++ and gfortran. I'm a complete newb to makefiles. When these codes are compiled as part of their respective programs, they are bug free (I'm taking a function from my C++ code, not main(), and trying to use it with the fortran code). Here's what I've got:

C++ Code:

#include <cmath>
#include <vector>
using namespace std;

extern"C" double ShtObFun(double x[], int &tp)
{
    return //double precision awesomeness
}

Fortran Code:

    subroutine objfun(nv, var, f, impass)
    implicit real(8) (a-h,o-z), integer (i-n)
c   initializations including tp, used below

    f = ShtObFun(var, tp)

    return
    end

Makefile (shows only files listed above):

all:
    g++ -c Objective_Functions.cpp
    gfortran -c -O3 opcase1.f
    gfortran opcase1.o Objective_Functions.o -fbounds-check -lstdc++ -g -o Program.out
    rm *.o

Error:

opcase1.o: In function 'objfun_':
opcase1.f:(.text+0xbd): undefined reference to 'shtobfun_'
collect2: ld returned 1 exit status

I have tried this a variety of other ways and they did not work. I can list those later if requested. Does anyone see the issue here?

The sites I've checked:

calling C++ function from fortran not C, Linking fortran and c++ binaries using gcc, , Calling C Code from FORTRAN, Cookbook - Calling C from Fortran, YoLinux - Using C/C++ and Fortran together

Edit (response to first answer):

If I rewrite C++ code as:

#include <cmath>
#include <vector>
using namespace std;

double ShtObFun(double x[], int &tp)
extern"C" double shtobfun_(double *x, int *tp) {
    return ShtObFun(x, *tp);
}
{
    cout << "reached tp = " << tp << endl;
    exit(1);
}

I get this error: error: expected initializer before 'extern' error: expected unqualified-id before '{' token

If I rewrite C++ code as:

#include <cmath>
#include <vector>
using namespace std;

double ShtObFun(double x[], int &tp);

extern"C" double shtobfun_(double *x, int *tp) {
    return ShtObFun(x, *tp);
}

double ShtObFun(double x[], int &tp)
{
    cout << "reached tp = " << tp << endl;
    exit(1);
}

The code will compile but the result I get is "reached tp = 0", while it should say "reached tp = 1" because I initialized tp to 1 in the fortran code (integer tp = 1). And I get the same issue if I simply declare the function as:

extern"C" double shtobfun_(double *x, int *tp)
{
     //cout, etc
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

declare or alias

extern"C" double ShtObFun(double x[], int &tp)

as

extern"C" double shtobfun_(double x[], int &tp)

see http://gcc.gnu.org/onlinedocs/gcc/Weak-Pragmas.html

That's you first step. Second step is to recognize that Fortran has no idea about references, moreover it passes all arguments as a pointer. so you F77 interface should be declared as:

extern"C" double shtobfun_(double x[], int *tp);

Putting it all together:

double ShtObFun(double x[], int &tp)
extern"C" double shtobfun_(double *x, int *tp) {
    return ShtObFun(x, *tp);
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...