- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
I have the following C function with derived types which I want to call from Fortran
typedef struct {
double x, y, z;
} Vector;
int remove_triangle (Vector *poly, int *polysize, Vector *v1, Vector *v2, Vector *v3);
On the Fortran side, I have this derived type a module called "types"
type,bind(C):: VECTOR
real(C_DOUBLE) x,y,z
endtype VECTOR
and in another Fortran source file, this interface declaration in the routine that's actually using the C code.
interface
integer(C_INT) function remove_triangle(poly, polysize, v1, v2, v3) BIND(C,NAME='remove_triangle')
use iso_c_binding
use types
integer(C_INT) polysize
type(VECTOR) poly(polysize),v1,v2,v3
endfunction
endinterface
This links fine under Windows but not under Linux. There, I get this error:
ld: trig_more.o: in function `trig_more_': trig_more.f90:(.text+0x3a1): undefined reference to `remove_triangle'
The C part of the code is built into a static library (.a) and with the nm tool, I can see the decorated name of the function I'm trying to link:
0000000000000060 T _Z15remove_triangleP6VectorPiS0_S0_S0_
while the Fortran object (.o) shows either the undecorated name or the C binding name I provided:
U remove_triangle
Both of the objects are on the linker command line and I even made sure that the .a is listed after the .o in the object list. I've tried both directly listing the .a in the list of objects and linking it through the -l flag. I've even tried listing the C .o file directly but get the same error.
So what am I doing wrong and how I can get this to build on both platforms ? The only inconsistency I can see in the declarations is the case sensitivity in the name of the derived type but since it's apparently not possible to use bind(C,NAME=...) on a type declaration and Fortran is case-insensitive, that's not something I seem to have control over...
Compilers used: ifort and icc version 15.0.0 20140723.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
That the C/C++ compiler created a decorated name for the symbol "remove_triangle" indicates that C++ name decoration took place. You may check that the source file and compiler command are asking for C compilation, not C++ compilation. You may also see if surround the "extern" declaration should be extern "C" {int remove_triangle (Vector *poly, int *polysize, Vector *v1, Vector *v2, Vector *v3);}
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
That the C/C++ compiler created a decorated name for the symbol "remove_triangle" indicates that C++ name decoration took place. You may check that the source file and compiler command are asking for C compilation, not C++ compilation. You may also see if surround the "extern" declaration should be extern "C" {int remove_triangle (Vector *poly, int *polysize, Vector *v1, Vector *v2, Vector *v3);}
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks for the tip; that was indeed the the problem. I wasn't familiar enough with name decoration to recognize this as the output of a C++ compiler.
It turns out that SCONS thinks that files with an uppercase .C extension are C++; renaming it back to lowercase .c forced the file to be compiled and linked as C.
mecej4 wrote:That the C/C++ compiler created a decorated name for the symbol "remove_triangle" indicates that C++ name decoration took place. You may check that the source file and compiler command are asking for C compilation, not C++ compilation. You may also see if surround the "extern" declaration should be extern "C" {int remove_triangle (Vector *poly, int *polysize, Vector *v1, Vector *v2, Vector *v3);}

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page