From: colin AT bird DOT fu DOT is DOT saga-u DOT ac DOT jp (Colin Peters) Subject: RE: exported variables from dll 15 Jun 1997 03:22:59 -0700 Approved: cygnus DOT gnu-win32 AT cygnus DOT com Distribution: cygnus Message-ID: <01BC7986.94EA68A0.cygnus.gnu-win32@gbird0> Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Original-To: "'Philippe GIACINTI'" Original-Cc: "'GNU-Win32'" Original-Sender: owner-gnu-win32 AT cygnus DOT com Philippe GIACINTI[SMTP:giac AT dalim DOT de] wrote: >I wish to define some variables in a dll and use them in another, on Unix I >have no problems: the variable is defined global in one .cc and extern in >another. >If I use the same code in Cygwin32, it seems that each dll have a local copy of >this variable ( ie: the addresses are different ). >I tried to do this with VisualC++, and it works if I use the directive >DllImport instead of extern. > >( in fact I have this problem in a dll which uses stdout, I found that >"_impure_ptr" was correctly initialized in main, but was null in the dll ) > >I'm really new in Cygwin32 and Windows environment, and I think (hope) it comes >from my ignorance. It's a little hard to be sure from the information you have given, but I think your problem is related to the way dlltool builds import libraries. Basically lets say you have a DLL with a function "Foo" and a variable "bar". Your .def file will look something like this: EXPORTS Foo bar First thing you should notice: dlltool cannot tell that one of these is a function and the other is a variable. Dlltool builds a import library basically consisting of functions which do something like this: Foo () { return __imp_Foo(); } bar () { return __imp_bar(); } __imp_Foo and __imp_bar are symbols in a special table that gets filled in with the *real* addresses of the Foo and bar symbols when the DLL that contains them is loaded at run time. So when you call Foo, you are actually calling a thunk function statically linked into your own code, which effectively looks up the real address of the function you wanted and calls it (all the arguments just pass straight through). But what happens to the variable? Well, if you do something like this in your code: x = bar; The symbol bar is defined and all that, but it's defined as a pointer to the *thunk function*! Thus, every dll or program that uses the bar variable will, indeed, have it's own copy, because they all have their own thunk. And, of course, that value will have absolutely nothing to do with what you wanted to do. In Visual C++ the __dllimport (or __dllexport, whatever) keyword tells the compiler directly that the given variable or function is imported from a DLL. The compiler can generate the appropriate code directly where any reference is made to the given symbol, whether it is a function call or variable reference. Thus, no thunks are necessary and variable references are correct. You also don't need a .def file or an import library at all. Gcc, as far as I know, does not have a mechanism for doing this (yet), so we have to use dlltool to fool the compiler into putting our function calls through a thunk. Unfortunately this messes up variable references. Here is a workaround that I use with the current system: In your header file do something like this: #ifdef DEFINING_DLL int bar; #else extern int* __imp_bar; #define bar (*__imp_bar) #endif This way when DEFINING_DLL is set (which you only do in the DLL which actually contains the variable) you get the normal int variable. In the other code which uses the variable any reference to bar becomes an indirect reference through the __imp_bar variable created by dlltool. This is a temporary solution of course. What *should* happen (IMHO) is that gcc should learn how to do that itself and generate the appropriate code for shared libraries (I would have thought they would do it for UNIX shared libraries anyway). We could then do away with dlltool and .def files altogether. Instead your headers might look like this: #ifdef DEFINING_DLL #define DLLSYMBOL __attribute__(__dllexport__); #else #define DLLSYMBOL __attribute__(__dllimport__); #endif int DLLSYMBOL Foo(); int DLLSYMBOL bar; or possibly even this: __dllexport int Foo(); __dllexport int bar; As a special wish list item I would like to be able to do something like this in C++: __dllexport class MyClass { ... }; And have all the member functions (and static variables) of the class reside in a dll. This would save me the hassle of generating ..def files for C++ classes, and the worries about the internals of virtual functions and inheritance from the exported class (and run time type information too, if supported). If this ever happens I will be an extremely happy camper. :) (By the way, I am not really suggesting syntax here, because I might have the attribute thing wrong, but I do think it would be nice to make it so that, either with a #define or directly, headers using MSVC __dllexport type constructs could be used with GCC.) As I said though, this is not yet the case, so you have to resort to the above trickery, which is ugly and dependent on the undocumented inner workings of dlltool. Would someone else on the list like to take up the question about _impure_ptr? I pretty much only use Mingw32, which has it's own DLL startup code that initializes stdout and so on (and doesn't use _impure_ptr), so I'm not in a position to know exactly what the problem there is. Anyway, good luck, Colin. -- Colin Peters - colin AT bird DOT fu DOT is DOT saga-u DOT ac DOT jp -- Saga University Dept. of Information Science -- http://www.fu.is.saga-u.ac.jp/~colin/index.html -- http://www.geocities.com/Tokyo/Towers/6162/ - For help on using this list (especially unsubscribing), send a message to "gnu-win32-request AT cygnus DOT com" with one line of text: "help".