calling C++ function from fortran not C - fortran

is it possible to call a C++ function from FORTRAN such as
#include <iostream.h>
extern "C"
{
void single_cell(void)
{
cout<<"Hi from C++";
}
}
So when I am using C it is working fine but with the C++ function it gives errors like
Undefined error to cout etc

Both g++ and gfortran, used as linkers, bring in extra libraries. That is why the Fortran/C++ combination is trickier than the Fortran/C combination ... just using the correct compiler as the linker won't work, you need to add a libary. Already suggested is to link with gfortran and specify the C++ runtime libraries. You can also link with g++ and specify the Fortran runtime libraries. See Linking fortran and c++ binaries using gcc for the details of both approaches.

Assuming you could have your Fortran code call into a C function, the problem is not the code but rather how you are linking. When you're linking C++ objects you need to also pull in the C++ runtime. If using GCC, link with the g++ command and it will pull in the parts you need.

Related

Barebones C++ without standard library?

Compilers such as GCC and Clang allow to compile C++ programs without the C++ standard library, e.g. using the -nostdlib command line flag. It seems that such often fail to link thou, for example:
void f() noexcept { throw 42; }
int main() { f(); }
Usually fails to link due to undefined symbols like __cxa_allocate_exception, typeinfo for int, __cxa_throw, __gxx_personality_v0, __clang_call_terminate, __cxa_begin_catch, std::terminate() etc.
Even a simple
int main() {}
Fails to link with
ld: warning: cannot find entry symbol _start; defaulting to 0000000000400120
and is killed by the OS upon execution. Using -c the compiler still runs the linker which blatantly fails with:
ld: error in mytest(.eh_frame); no .eh_frame_hdr table will be created.
Is it a realistic goal to program and compile C++ applications or libraries without using and linking to the standard library? How can I compile my code using GCC or Clang on Linux? What core language features would one be unable to use without the standard library?
You will basically find all of your questions answered at osdev.org, but I'll give a brief summary anyway.
When you give GCC -nostdlib, you are saying "no startup or library files". This includes:
crti.o, crtbegin.o, crtend.o and crtn.o. Generally kernel developers only care about implementing crti.o and crtend.o and let GCC supply crtbegin.o and crtend.o by passing -print-file-name= to the linker. Generally these are just stubs that consist of .init and .fini respectively, leaving room for GCC to shove the contents of crtbegin.o and crtend.o respectively. These files are necessary for calling global constructors/destructors.
You can't avoid linking libgcc (the "low-level runtime library" (-lgcc) because even if you pass -nostdlib GCC will emit calls to its functions whenever you use it, leading to inexplicable linking errors for seemingly no reason. This is the case even when you're implementing/porting a C library.
You don't "need" libstdc++ no, but typically kernel developers want it. Porting a C library then implementing the C++ standard library from scratch is an extremely difficult task.
Since you only want to get rid of the "standard library", but keeping libc (on a Linux system) you're essentially programming C++ with just a C library. Of course, there's nothing wrong with this and you do you, but ultimately I don't see the point unless you plan on developing a kernel.
Required reading:
OSDev's C++ page - If you really care about RTTI/exception support, it's more annoying to implement than it sounds. Typically people just pass -fno-rtti or -fno-exceptions and then worry about it down the line or not at all.
"Standard" is a misnomer. In this context it doesn't mean "the library (set of functions, classes etc) as defined by the C++ standard" but "the usual set of libraries and objects (compiled files in a certain format) gcc links with by default". Some of those are necessary for most or even all programs to function.
If you use this flag, it's your responsibility to provide any missing functionality. There are several ways to do so:
Cherry-pick libraries and objects that your program really needs out of the default set. (Makes little sense as the result will most probably be exactly the same as with the default link flags).
Provide your own implementation of missing functionality.
Explicitly disable, through compiler flags, language features your program isn't using. I know of two such features: exceptions and RTTI. This is needed because the compiler needs to generate exceptions-related code and RTTI info even if these features are not explicitly used in this module.

error occured when fortran code called c code

I have used a method in a reference book about fortran codes calling c codes. The method is that if your function name in the c codes are capitalized, you may not make additional changes in your fortran code. The following is my code.
Source1.f90:
program main
implicit none
call c_subprint()
endprogram
ccode.c:
#include <stdio.h>
#include <string.h>
#ifdef _cplusplus
extern "C" {
#endif
void _stdcall C_SUBPRINT()
{
int a;
printf("%s\n","kk");
scanf("%d",&a);
}
#ifdef _cplusplus
}
#endif
The error message is that the main function cannot find out _C_SUBPRINT(LNK2019). But I have already added the .lib generated by the c code to the fortran code. And my code is almost the same as that in the reference book. what is wrong?
Different Fortran compilers generate calls differently. Many add underscores to routine names to avoid name conflicts with C-code. Its very hard to say whether or not you should exactly follow the example of an unnamed reference book. In the past, to mix Fortran and C, you have to understand some of the compiler internals. Here the Fortran compiler appears to have added an underscore to the start of the name. You could probably fix the problem by adding that in your C++ code. But that won't be portable and in principle could change with compiler versions. There is a better way: the Fortran ISO_C_Binding. This is part of the Fortran language standard and therefore standard and portable. Examples are given in the gfortran manual in the Chapter "Mixed-Language Programming" and in other questions on Stackoverflow.
From the inclusion of _stdcall I deduce you are probably using a Windows platform. Unfortunately I'm working on a Mac, so things may not be exactly the same. However, the following works for me (small changes from your code) to get a mix of Fortran and C code working together. Note - on my Mac, the gcc compiler does not include Fortran, so I used a separate Fortran compiler gfortran which I downloaded from a link at http://hpc.sourceforge.net - where instructions for installation could also be found.
program src1.f90:
program main
implicit none
call C_SUBPRINT()
endprogram
program ccode.c:
#include <stdio.h>
#include <string.h>
void c_subprint_()
{
printf("hello world!\n");
}
Note I took out the #ifdef sections - I was using pure C, so it was not needed; more importantly, note the underscore after the function name
I compiled these two modules as follows:
gcc -c ccode.c -o ccode.o
gfortran src1.f90 ccode.o -o hello
After which I can run
./hello
And get the expected output:
hello world!
Without the underscore, the linker complains about unknown symbols. There is an option in the compiler to turn off "name mangling" with the underscore. You can check your specific compiler to see how that would be done - but that's almost certainly the problem you are having.

How configure include path and use standard library with gcc compiler?

I know this topic was few times there, but I can't get satisfactory answer.
C:\Users\Krzysiek>gcc test.c
test.c:3:20: fatal error: iostream: No such file or directory
compilation terminated.
This is what I try to do
#include <iostream>
using namespace std;
int main ()
{
cout << "Hello World!";
return 0;
}
Simple program with "include"
I've heard of LIBRARY_PATH. So I've setted that. Still this same error I have.
GCC provides wrappers around calling its various compilers.
You are using gcc, which is for C (and consequently will not include or link the C++ standard library; the compiler would go on to complain about the rest of your code, too, since it's not valid C);
Use g++, which is for C++.
Also try to use a conventional extension for C++ source files, which is .cc, .cxx or .cpp.
Use g++ instead: it will link to the c++ standard library.
When you use the gcc command, gcc looks at the file extension to decide which language to use to compile. As you used a .c file, gcc will switch by default to C.
# Use the C compiler
gcc test.c
# Use the C++ compiler
gcc test.cpp
To choose a different language, you can use the -x option:
# Use the C++ compiler even if the extension is .c
gcc -xc++ test.c
Another method of using the C++ compiler is to use g++ in the command line. This is the preferred way, as it links with the correct libraries.
# Use the C++ compiler
g++ test.c

resolving non-unique symbols between c++ wrapper libraries for fortran subroutines

I am working with two sets of FORTRAN code, for example, codeA.f and codeB.f. In each set of code there are subroutines with the same name, but which perform significantly different tasks (as well as common blocks).
codeA.f:
subroutine init
c do something here ...
end
codeB.f:
subroutine init
c do something else here ...
end
I create two C++ wrappers for both routines (wrapperB is identical, but swap B for A).
wrapperA.cpp:
namespace codeA {
extern "C"{void init_();}
void init() {init_();}
}
wrapperA.h:
namespace codeA {
init();
}
I then compile the two wrappers into shared libraries.
Makefile:
codeA.o : codeA.F
g77 -fno-automatic -fPIC -O3 -c codeA.f -o codeA.o
wrapperA.o : wrapperA.cpp
g++ -fPIC -c wrapperA.cpp -o wrapperA.o
libwrapperA.so : codeA.o wrapperA.o
g++ -fPIC -shared -lg2c codeA.o wrapperA.o -o libwrapperA.so
Finally, I want to be able to call the two different subroutines from the same program.
main.cpp:
#include "wrapperA.h"
#include "wrapperB.h"
main {
wrapperA::init();
wrapperB::init();
}
The main program is linked against the two shared wrapper libraries.
Makefile:
main : main.cpp
g++ main.cpp -I. -L. -lwrapperA -lwrapperB -o main
Everything compiles and there are no complaints. However, when the program "main" is run, the init() commands perform the same action, dictated by which of the wrapper libraries was linked against first. However, if I link against only one of the libraries, the linker complains about missing symbols.
I have two question about this:
a) Is it possible to link against two different FORTRAN routines using only namespaces or some similar method to what I am doing? If so, what am I doing wrong?
b) If a) is not possible, is it possible to resolve the conflicts by instructing the compiler to append the symbols with some unique identifier when creating the FORTRAN objects (I am using gcc version 4.1.2 20080704 (Red Hat 4.1.2-51))?
Thanks for any insight into this.
Your compile commands show the use of g77, which is no longer maintained and also implies the use of a very old version of Fortran (i.e., FORTRAN 77). You are also using an old version of gcc. If you use gcc and gfortran of version 4.3 or higher -- preferably 4.4 or higher -- then you can use the Fortran 2003 ISO C Binding to solve your problem. In the Fortran code you can assign externally visible names to the routines with the "bind" option of the ISO C Binding. Just assign different "bind" names to the two routines. Then they won't clash at the library & linker level:
In one Fortran file use
subroutine init (stuff...) bind (C, name="init_V1")
and the other file
subroutine init (stuff...) bind (C, name="init_V2")
and the routines will be visible to C, C++, the linker, etc. as init_V1 and init_V2 without clashing.
Have a look at this SO question, which is very similar to your problem : Static and shared library symbol conflicts?
Basically, you have two shared libraries defining different symbols : wrapperA::init() and wrapperB::init() ; but also conflicting symbols : _init__(). So when the linker resolves, it use the first of the conflicting symbol it find.
If you remove the unneeded external visibility of _init__() in your libraries by using the techniques given in the SO question : http://www.gnu.org/software/gnulib/manual/html_node/Exported-Symbols-of-Shared-Libraries.html, then I think you will have solved your problem. Each wrapper::init() will then call internally it's proper _init__() without any conflict.

Call C/C++ code form a fortran program in visual studio? (How to compile mixed C and fortran code in visual studio)

i am looking for a way, how i can integrate a c++ code with fortran code (i want simply call some C/C++ functions in the fortran code).
I have found some proposals for gcc or console compilers, but i have not any idea how to translate this approach to solve integrationproblem within the visual studio.
At the time I am thinking about creating a dll form c++ code and calling it from Fortran code.
Has someone already seen a solution? Or what is about overhead for calling function from dll? My fortran code transfers a lot of memory into C function, is there any problems, if i would solve this problem with dll?
thx.
PS
I am using Visual Studio 2008 Prof and Intel compilers 10
PPS
I think, i have to specify more concrete, what i want: i want to compile a fortran project in visual studio, which uses some C functions.
There is a new way to do this that has many advantages -- use the Fortran 2003 ISO C Binding. This is a standard and therefore largely OS and language independent way of interfacing Fortran and C (and any language that will use C calling conventions). Intel Fortran 11 supports along with numerous other compilers -- not sure about version 10. Using the ISO C Binding, you can match any C name (any case), don't have to worry about underscores (and variations between compilers) and can specify the types and calling methods (by reference, by value) for the arguments. Intel provides some examples in a folder with their compiler; there are also examples in the gfortran manual and a discussion of additional considerations for Windows. There are previous questions & answers here and on the Intel Fortran forum.
I integrated C and Fortran about 20 years ago and maintained this integration up to 5 years ago. The tricks I used were:
I noticed that the Fortran compiler puts all symbols in uppercase, so make sure your C/C++ functions are written in uppercase as well. To verify how symbols are put in the .OBJ file, use DUMPBIN.
The Fortran compiler does not understand the name-mangling done by the C++ compiler. Compile all your C++ functions using the C style convention (using extern "C")
Arguments in Fortran are always put on the stack using references/pointers. Therefore, use pointer-arguments in your C function.
To be honest, I gave up integrating C and Fortran when I switched to VS2005, so things might have changed since then. Nevertheless, it's still a good idea to use DUMPBIN to see what kind of symbols the Fortran compiler produces, and adjust the compilation of C/C++ sources to fit with that.
We do it where I work.
Assuming you are using the Intel Fortran compiler, look up its docs. By default Intel Fortran passes everything by reference and (I believe) uses the C calling convention, with an all caps identifier. Strings are a particular issue, as Fortran likes to pass the length as a hidden parameter, with a compiler setting for where it goes in the parameter list.
A wise programer doesn't rely on defaults (where a mistake can lead to undefined behavior), and will use the intel INTERFACE statements to specify calling convention, parameter passing, and the link name for the routine. The information on this page (ATTRIBUTES Properties and Calling Conventions) is a must-read. In particular you need it to understand the arcane rules for when and where string length parameters will be passed. I have a printout of it that I keep on my person. :-)
One other thing to note is that versions of VisualStudio past 6 don't like mixed Fortran and C projects. We solved the problem by creating custom project files calling out to makefile, but that's a PITA. I'd suggest going with the flow and using separate projects unless you are doing this a lot like we are.
Solution found:
solution link
i have had several problem with linking, which could be solved with adding in project properties.
code for testing:
#include <stdio.h>
extern "C"
{
void f()
{
printf("hi from c\n mega test");
}
}
fortran code
PROGRAM HelloWorld
use, intrinsic :: iso_c_binding
implicit none
interface
subroutine f( ) bind( c )
use, intrinsic :: iso_c_binding
end subroutine f
end interface
call f
END PROGRAM HelloWorld
on demand i can upload the testproject. thanks all, hopefully it was my last problem with c and fortran
I was able to build obj from fortran sources thanks to the Custom Build Tools of Visual Express 2010. I guess it is also possible in Visual Studio.
If you want to mix C and Fortran together, there is a good tutorial here. It was written for gcc compilers but you should be able to learn how to deal with name mangling easily.
Depending on the compiler, compiled subroutines/functions are Uppercase/lowercase, with a trailing underscore, with a leading underscore,... For a succesfull linkage, you could use dumpbin tools to see how the name appears in the objectfile.
An other way is to use iso_c_binding modules, but it is available with Fortran 2003 only.
This is the how it works with gcc and console
c.c:
#include <stdio.h>
void f_()
{
printf("Hi from C\n");
}
fortran.f90
PROGRAM HelloWorld
CALL f
END PROGRAM HelloWorld
Makefile
SRCDIR=.
all: clean release run
release:
gcc -c c.c -o c.out
gfortran -c fortran.f90 -o fortran.out
gfortran -o out.exe fortran.out c.out
run:
out.exe
clean:
#$(ZSHMAGIC) rm -rf *.exe core* *.o a.out 2> /dev/null
One other question: have i always add '_' after c-function name, which i use in the fortran program?