diff --git a/dtool/src/dtoolbase/dtoolsymbols.h b/dtool/src/dtoolbase/dtoolsymbols.h index 10330b272a..36af9a698e 100644 --- a/dtool/src/dtoolbase/dtoolsymbols.h +++ b/dtool/src/dtoolbase/dtoolsymbols.h @@ -23,22 +23,49 @@ /* This file defines a slew of symbols that have particular meaning only when compiling in the WIN32 environment. These symbols are - prefixed to each class declaration, and each static data member - within a class, that is to visible outside of a DLL. + prefixed to each class declaration, and each global function, that + is to be made visible outside of a DLL. - We need to specify a particular string for *exporting* the symbols - when we are compiling a DLL, and for *importing* the symbols when - we are accessing the DLL (that is, compiling some code that will - link with the DLL, e.g. an executable program or a different DLL). - The trick is that we have to be particular about whether we're - exporting or importing the symbols for a specific DLL. + The problem is that in Windows, you must prefix each DLL-public + symbol with "__declspec(dllexport)" when you are compiling the DLL, + but with "__declspec(dllimport)" when you are compiling code that + links with the DLL. This strange convention means that you must, in + principle, have two different .h files for a DLL: one to use for + compiling the DLL (it must export all of the symbols), and a + different one for presenting the public interface for other users to + use (it must import all of the same symbols). - We achieve this by defining a unique pair of symbols for each DLL. - When we are building a particular DLL, we define the manifest - BUILDING_libname on the command line. This file then discovers - that manifest and toggles the flag to *export* only for the symbols - that belong to that DLL; the symbols that belong in each other DLL - are set to *import*. + In practice, of course, maintaining two different .h files is silly + and error-prone; almost everyone solves this problem by defining a + macro that evaluates to "__declspec(dllexport)" in one case and + "__declspec(dllimport)" in another case. Many systems use the + system macro _DLL to switch between these two case, which works well + in a simple system because _DLL is defined only if compiler is + currently generating code for a DLL. So you can export the symbols + if _DLL is defined, and import them if it is not defined. + + However, this fails if you are compiling a DLL that wants to import + symbols from another DLL, since in this case _DLL is defined, but + the symbols in the other DLL need to be imported, not exported. + + In the general case of compiling multiple DLL's that might reference + each other's symbols, we need have a separate macro for each DLL. + Then when we are compiling code for each DLL, the macro for that + particular DLL evaluates to "__declspec(dllexport)", exporting all + the symbols from the DLL, while all the other DLL's macros evaluate + to "__declspec(dllimport)", importing all the symbols from the other + DLL's. + + That is the approach we have taken here in Panda. When we are + compiling code for a particular DLL, the build scripts define the + macro BUILDING_libname on the command line. This file then uses + that macro to define EXPCL_libname appropriately for each DLL; this + macro is then used to prefix each symbol to be exported from the + DLL. The macro name stands for "export class", since it is used + most often to mark a class for export, although the same macro can + be used to export global functions. (We also define EXPTP_libname, + which is used in conjunction with exporting template instantiations, + another dicey task in Windows. It is used far less often.) Of course, this whole thing only matters under WIN32. In the rest of the world we don't have to deal with this nonsense, and so we