-shared option

Ranjit Mathew rmathew4lists@hotmail.com
Thu Apr 3 10:35:00 GMT 2003


> You need to mark DATA
> 
> > ---------------------------- 8< --------------------------------
> > EXPORTS
> >     _ZN3Foo3barEv
> >     _ZN3FooC1Ev
>       _ZN3Foo6class$E DATA
>       _ZTVN3FooE DATA
> > ---------------------------- 8< --------------------------------
> 
> The other way:
> dlltool --output-def foo.def --export-all foo.o
> and then comment out what you don't want to export.

Did this, tried "-Wl,--export-all-symbols", "-Wl,--enable-auto-import",
etc. but am still getting the NullPointerException. :-(

On closer inspection, among the lines:

    System.out.println( "Test 1...");
      Foo f;
    System.out.println( "Test 2...");
      f = new Foo( );
    System.out.println( "Test 3...");
      f.bar( );
    System.out.println( "Test 4...");

the NullPointerException happens just at the line creating the
new Foo object, so a WAG would be that the class definition is
not being loaded properly. 

(Which suddenly makes me realise that I haven't got the foggiest 
idea about how GCJ is able to determine class layout, method and 
variable information etc. when it doesn't have the convenience 
of a header file as in C++... Anyone care to enlighten?

[And *this* tells me that I seem to have a penchant for forking
off off-topic threads in a discussion. ;-)])


> You can only access DATA like this
> 
> *_imp__ZTVN3FooE
> 
> so you either 
> (1) need the dllimport for imported objects in client code  
> (2) use --enable auto-import and (probabaly) --enable-runtime-pseudo-reloc to
> fixup

This merits a bit more explanation for the non-Windows folks
in here I guess (time to show off some recently acquired, 
probably flaky, knowledge ;-)):

As the harried non-Windows members of this list might know
by now, a DLL on Windows needs to explicitly export symbols 
corresponding to a variable or a method for the linker/loader
to be able to resolve it. This is done by either marking
them "__declspec(dllexport)" or explicitly listing them in
a separate exports definition file ("DEF file").

For a call to a method that is declared *without* any
import attributes, the generated call would look roughly
like:

    call _foo

Now if the object file containing "foo( )" is linked in
directly or if it is in a statically linked library, every
thing is hunky dory.

However, if "foo( )" is defined in a dynamic library, the
linker puts in the following magic (roughly) for this case:

    _foo:
        movl    __imp__foo, %eax
        jmp     *%eax

"__imp__foo" comes from the import table of the executable
and is "fixed up" by the Windows loader based on the loaded 
"foo" DLL.

If "foo( )" were to be declared "__declspec(dllimport)", 
this double-indirection can be avoided and the program 
would be that much faster (noticeably so on older Pentiums).

So how does one declare "foo( )" in such a way that
it gets defined in the best manner possible for 
statically linked-in clients as well as dynamically linked in
clients? Something like the following is used:

    #ifdef LIBFOO_DLL
        #ifdef FOO_IMPLEMENTATION
            int __declspec(dllexport) foo( void);
        #else
            int __declspec(dllimport) foo( void);
        #endif
    #else
        int foo( void);
    #endif

Gross, eh? A similar mechanism can be seen today in the "jni.h"
header in GCJ (see "JNIIMPEXP").

For data, a similar magic takes place - the 
"--enable-auto-import" flag makes the linker link "_bar" to
"__imp__bar".

The point of all this explanation being that if GCJ has
to generate nice code that works with classes defined in a
DLL as well as in a static library *without* the user
being able to indicate it using an attribute, we need
some more magic...

 
> Note there are fish-hooks in C++ with dllimport and virtual methods and
> artificial variables (eg, typeinfo objects) generated by the compiler. I expect
> the same in Java.

This was OHT (Over-Head Transmission) for me... :-(

Ranjit. 



More information about the Java mailing list