This is the mail archive of the cygwin@cygwin.com mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

g77: getarg returns nothing if called in dll (cygwin)


I've asked this already on the cygwin mailing list but nobody seems
interested there.  So I'll try here as this seems to be a libg2c issue.
In short I think libg2c needs to be built as a dll (shared library) to 
solve my problem, see below.

I am trying for the first time to build a dll and I've stumbled across this:
g77 getarg returns nothing if called from a dll.  This is what I did:

Test> cat test.f
        program test
        implicit none

        character x*132
        integer i

        call geti( x, i )

        end

Test> cat geti.f
        subroutine geti( image, len_image )
        implicit none

        character*(*) image
        integer len_image

        character*20 prg_name

        call getarg( 1, prg_name )
        print *, 'getarg''ed: |'//prg_name//'|'

        end

Test> g77 -c test.f
Test> g77 -c geti.f
Test> g77 test.o geti.o
Test> ./a blah
 getarg'ed: |blah                |
Test>

Ok, that works.  Here's the problem:

Test> dllwrap --driver-name g77 --implib libgeti.a  --export-all -o geti.dll geti.o
dllwrap: no export definition file provided
dllwrap: creating one, but that may not be what you want
Test> ls
geti.dll  geti.f  geti.o  libgeti.a  test.f  test.o
Test> g77 test.o -L . -lgeti
Test> ./a blah
 getarg'ed: |                    |

Now there is nothing between |...|


Some analysis:

A Fortran program calls a main that is defined in libF77 and lives in libg2c.  This 
main looks something like this:

int f__argc;
char** f__argv;

int main( int argc, char **argv ) {
   f__argc = argc;
   f__argv = argv;
   /* call actual Fortran main program */
}

And getarg in libF77 does this:

extern int f__argc;
extern char** f__argv;
getarg_(int *n, char *s, long l ) {
...
   s = f__argv[*n];
...

}


Both main.o and getarg.o are statically linked from libg2c.  So test.o pulls it in from libg2c
and the dll geti.dll gets its own copy from libg2c.  Yuck.

To solve this the declaration would have to be reversed:

extern __declspec(dllimport) int f__argc;  /* make this extern and get
                                                                  * it from dll */
extern __declspec(dllimport) char** f__argv;

int main( int argc, char **argv ) {
   f__argc = argc;
   f__argv = argv;
   /* call actual Fortran main program */
}

and (actually libf2c/libF77/setarg.c)

int f__argc;          /* this is now defined here instead of in main.c*/
char** f__argv;
getarg_(int *n, char *s, long l ) {
...
   s = f__argv[*n];
...

}

If we do this, however, we *have* to link against a shared library because
main.c is defined to find f_argc in a dll.  So we'd need two different versions
depending on whether the Fortran program will link against another Fortran
dll or not.

The only way out of this I see is to make libg2c itself a dll.  Then we wouldn't
have to change any definitions except that I don't know if main.o may be in
a dll.  


Are there any plans to make libg2c a shared library?  I'd be happy to help
with it but I would need help from other people who know the build
procedures better (the TODO file talks about a libtool I don;t know) and
also maybe libg2c as to where there could be problems if made a shared
library.

Thanks,
Michael


--
Want to unsubscribe from this list?
Check out: http://cygwin.com/ml/#unsubscribe-simple


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]