I want to call a function which is both in a c++ parent class "inval" and in the c++ derived class "SMval", from Fortran. The function I want to call is included in a bigger code which I would like to interface to my fortran. I have written the following code (3 files)
In library_wrapper.h:
#include "classes.h"
#include "SMval.h"
#ifdef __cplusplus
//Forward declarations of classes
class inval;
class SMval;
extern "C" {
#endif
void* createinval_();
void destroyinval_(void* instance);
void* createSMval_();
void destroySMval_(void* instance);
void invalsetWrapper_(const int idx, const double val);
void SMvalsetWrapper_(const int idx, const double val); // Declaration of the wrapper function
#ifdef __cplusplus }
#endif
In library wrapper.cpp:
#include "library_wrapper.h"
#include "classes.h"
#include "SMval.h"
#include "Cplx.h"
#include <iostream>
#include <string.h>
extern "C" {
void* createinval_() {
return new inval();
}
void* createSMval_() {
return new SMval();
}
void destroyinval_(void* instance) {
delete static_cast<inval*>(instance);
}
void destroySMval_(void* instance) {
delete static_cast<SMval*>(instance);
}
void invalsetWrapper_(const int idx, const double val) {
inval obj;
return obj.set(idx, val);
}
void SMvalsetWrapper_(const int idx, const double val) {
SMval obj;
return obj.set(idx, val);
}
}
and finally the main fortran:
PROGRAM main
implicit none
CALL CREATEINVAL()
CALL CREATESMVAL()
CALL INVALSETWRAPPER(12, 1/137.03599976)
CALL SMVALSETWRAPPER(1, 91.1876)
END
I am compiling on MAC Sonoma:
clang++ -g -std=c++11 -c library_wrapper.cpp
ld -r allothersobjectfiles.o library_wrapper.o -o combined_library.o
clang++ -shared -o liblibrary.a combined_library.o
gfortran -ffixed-line-length-none fortran.f -o main -L. -llibrary
But I get
ld: Undefined symbols:
_createinval_, referenced from:
_MAIN__ in ccPLQP9I.o
_createsmval_, referenced from:
_MAIN__ in ccPLQP9I.o
_invalsetwrapper_, referenced from:
_MAIN__ in ccPLQP9I.o
_smvalsetwrapper_, referenced from:
_MAIN__ in ccPLQP9I.o
collect2: error: ld returned 1 exit status
I tried to create a static library and link it, but it is still not working
To do that as properly as possible, you should use the C/Fortran interoperabilty features of Fortran, based on the iso_c_binding Fortran module
For instance, to call the
invalsetWrapper_function, your Fortran code should look like:Note that the interoperability assumes the use of pairs of compilers (that is, you should use
gccalong withgfortran), even if it often works when mixing compilers (but without any guarantee).