Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

symbol table problem

Intel_C_Intel
Employee
1,745 Views
Hi,
I have a problem with the linking of a static library.
The compiler error is that it doesn't find the symbols. I normally work in linux, but now I need to compile my code in windows.
I'm not really sure how I can see the symbol table in the library. I tested the library with compaq visual fortran and it's working perfectly. The same occurs in linux with the intel compiler 9.0

Can someone help me with this ??

thanks a lot!!

clabra
0 Kudos
14 Replies
Steven_L_Intel1
Employee
1,745 Views
dumpbin -symbols foo.lib

Do this from a "build environment for Fortran IA-32 applications" window.
0 Kudos
Intel_C_Intel
Employee
1,745 Views
Thank you Steve.

The problem was the calling convention for the external subroutine. Now I resolved almost everything, but one of the subroutines is called with the name "BEGINRESULTHEADER@32" and in the library the symbol is "BEGINRESULTHEADER@36" ....
Exist solution for this kind of problem ??? maybe using !DEC ??

thanks
0 Kudos
Steven_L_Intel1
Employee
1,745 Views
You have a mismatch in expectations for the number and/or datatypes of the arguments. My guess is that the call is passing a non-character where the routine is expecting a character argument. These need to match.
0 Kudos
Intel_C_Intel
Employee
1,745 Views
I made changes with the character argument in the subroutine, but the new symbol was "BEGINRESULTHEADER@40". Maybe the problem is with the implementation of the libray. It was written in C, with a cfortran.h interface to fortran.
(http://www.gidhome.com/support/gidpost.subst)

I don't sure about the work of the cfortran.h with the intel compiler. In unix it worked perfectly.
0 Kudos
Jugoslav_Dujic
Valued Contributor II
1,745 Views
As I see:
int GiD_BeginResultHeader(
char * Result,
char * Analysis,
double step,
GiD_ResultType Type,
GiD_ResultLocation Where,
char * GaussPointsName);

There are 6 arguments, 3 of which are characters; that gives (6*4) + (3*4) = @36 bytes. I assume there's a Fortran wrapper routine in the library, which takes care about proper calling of C version (_GiD_BeginResultHeader, which supposedly has total of 28 bytes (6*4) + extra 4 for double-by-value).

Thus, it seems it's still your error?

Jugoslav
0 Kudos
Intel_C_Intel
Employee
1,745 Views
thanks Jugoslav.

Now I see it was my error ....
I used an example that not work, and I used "NULL" in "GiD_ResultLocation Where" argument.
( character(4) :: NULL = char(0)//char(0)//char(0)//char(0) )

by the way, someone know if it's possible to use this interface without setting the call convention with "CVF"?
In my routine I can't use other modules.
0 Kudos
Jugoslav_Dujic
Valued Contributor II
1,745 Views
Well, yes, but not without a hassle.

I took a brief look at the GiD package but I didn't find INTERFACE statements, which would take care about these details. Thus, I assume that GID_WHATEVER functions are Fortran wrappers burried inside the library and built with CVF.

So, if you'd like to call these with the correct calling convention (CVF) but having the rest of the code with another calling convention (default), you have to spell out the interfaces yourself (or, alternatively, write yet another wrapper file). If I recall correctly, there isn't such thing as !DEC$ATTRIBUTES CVF, (which would ease you the job), so you'll need something like:

!DEC$ATTRIBUTES STDCALL, DECORATE, REFERENCE, MIXED_STR_LEN_ARG, ALIAS "GID_WHATEVER": GID_WHATEVER.

(Maybe just the above declaration is enough but I'm not sure about it, or maybe the full interface body is required; try it yourself).

Jugoslav
0 Kudos
Intel_C_Intel
Employee
1,745 Views
Looking at the source of the library you can see that it was written completely in C, and the interface is the cfortran library ( I don't really know how this interface works!! ). I understand that the library does not recognize the intel compiler (maybe I'm wrong) .... but in unix (with intel) I use it without problem. The problem occurs only in Windows.



The use of the "intel" directives is an easy option, but my idea is to make a standard code. In unix I use intel and G95. Maybe to write my own wrapper is a good option. I made this with other libraries.


clabra

Message Edited by clabra on 12-14-2005 09:20 AM

0 Kudos
Jugoslav_Dujic
Valued Contributor II
1,745 Views
I took a brief look onto it. DUMPBIN reveals that GID_FOO@n (fortran-callable) version of exported functions originate from file gidpostfor.c. There, they're defined using CFortran.h macros FCALLSCFUN*.

Since CFortran.h is pretty difficult to untangle, your best bet would be to:
- Find a newer version of CFortran.h supporting IVF on Windows (the version shipped with GiD library is pretty old, since 2001.)
- Replace the CFortran.h in the GiD package with that version
- Rebuild the GiD library.

This CFortran version looks like a good candidate... checking... no it seems it isn't. Uh.

Try searching or posting on comp.lang.fortran I googled some hints that it's possible, but nothing definitive.

Jugoslav
0 Kudos
Intel_C_Intel
Employee
1,745 Views
Thanks Jugoslav ....

I found cfortran.h version 4.4-8, but the support for the intel compiler is via a patch ?? I didn't use it, but I will make some tests.
For now, I wrote my own wrapper for the library, without cfortran, and it worked perfectly. 2 files, one in C (replace the cfortran interface gidpostfor.c ) and the other is a fortran module who call the library.

fortran_wrapper_gidpost.c :
...
#include "gidpost.h"
...
void C_OPENPOSTMESHFILE( char* name, int* mode )
{
GiD_OpenPostMeshFile( name, mode[0] )
}
...
...

!-------module_gidpost.f90 -------!
module gidpost
....
....
suboutine GiD_OpenPostMeshFile( fname, mode )
character(*), intent(in) :: fname
integer, intent(in) :: mode

call C_OPENPOSTMESHFILE( name, mode )

end subroutine GiD_OpenPostMeshFile
....
end module gidpost
0 Kudos
Jugoslav_Dujic
Valued Contributor II
1,745 Views
I'm affraid that it works perfectly by chance -- character arguments are a pain.



Fortran passes the length of char string around; C expects char(0)-termination. Due to ifort's __cdecl calling convention, you won't screw the stack if you omit the length argument (as you did), which is passed at the end of argument-list, but you didn't take care about char(0)-termination. So, if a binary zero happens to be in memory after the actual argument name, it will "work", but if it doesn't, the outcome can be pretty much anything.



Best, you should declare an int namelen argument at the end of char-list, malloc() a char array of namelen+1 elements, strcpy the name argument to it and assign a � at positon namelen. THEN you can pass it to the "real" C routine. (If there are some output character arguments, reverse the procedure). I'm pretty sure that's what CFortran.h wrappers do.



Jugoslav

Message Edited by JugoslavDujic on 12-16-2005 12:57 PM

0 Kudos
Intel_C_Intel
Employee
1,745 Views
I believe you about the cfortran.h, but I think maybe it's good an option more "simple" for the wrapper.



You are right about the problem with the strings. my first idea was to use an array of character(1) ( like iso_varying_string module), but I had some of garbage in the end of the array. After your comment I use this modification:



!------

suboutine GiD_OpenPostMeshFile( fname, mode )

character(*), intent(in) :: fname

integer, intent(in) :: mode



integer :: i, n

character(1) :: c_fname(len(fname))



n = len(fname)

forall (i=1:n) c_fname(i)=fname(i:i)

c_fname(n+1) = char(0)



call C_OPENPOSTMESHFILE( c_fname, mode )


end subroutine GiD_OpenPostMeshFile
!------


It's working. What do you think about this possibility ?

clabra

Message Edited by clabra on 12-16-2005 04:36 AM

0 Kudos
Jugoslav_Dujic
Valued Contributor II
1,745 Views
But you're overwriting the last character of name now. Where is C_OPENPOSTMESHFILE defined? Is it a C or Fortran routine from GiD, or one of yours?

I'd still stick to C wrappers, as they're more flexible (if you want to keep portability of Fortran part). Still more, I'd still prefer to have a working version of CFortran.h. (By the way: have you tried building CFortran.h by #define-ing symbol corresponding with some of older compilers' listed? Ifort (unlike CVF) shares most of argument-passing mechanism with other compilers.

So, a wrapper for IVF written in C for GiD_OpenPostMeshFile(char*, int) would look like:

extern "C" void F_OPENPOSTMESHFILE(char* name, int* mode, int namelen)
{
//prolog - needed only if name is INTENT(IN)
char* cname = new char[namelen+1];
memcpy(cname, name, namelen);
cname[namelen] = '�';

GiD_OpenPostMeshFile(cname, *mode);

//epilog (blank-padding) - needed only if name is INTENT(OUT):
strncpy(cname, name, strlen(cname))
for (int i=strlen(cname); i name = ' ';

delete[] cname;
}

Jugoslav

Message Edited by JugoslavDujic on 12-16-2005 02:33 PM

0 Kudos
Intel_C_Intel
Employee
1,745 Views
C_OPENPOSRMESHFILE is a EXTERN routine of my wrapper file in C.

If I make :
forall(i=1:len(fname)) c_fname(i)=fname(i:i)
c_fname(len(fname)+1) = char(0)

is "c_fname" equivalent to your "cname" string ???
My idea it was to pass directly the string like an C character array. I'm not sure if is correct, but it's work in my case.
Your implementation of the wrapper is very interesting, but don't have problem with the "name" argument in C???

clabra
0 Kudos
Reply