Looking for a DL_xxPORT macro export
Somebody recently added DL_IMPORT macros to two module init functions that already used their names in DL_EXPORT macros (pyexpat.c and parsermodule.c). On Windows, that yields the result I (naively?) expected: compiler warnings about inconsistent linkage declarations. This is your basic Undocumented X-Platform Macro Hell, and I suppose the Windows build should be #define'ing USE_DL_EXPORT for these subprojects anyway (?), but if I don't hear a good reason for *why* both macros are used on the same name in the same file, I'll be irresistibly tempted to just delete the new DL_IMPORT lines. That is, why would we *ever* use DL_IMPORT on the name of a module init function? They only exist to be exported. baffled-in-reston-ly y'rs - tim
Tim Peters writes:
Somebody recently added DL_IMPORT macros to two module init functions that already used their names in DL_EXPORT macros (pyexpat.c and parsermodule.c).
That was me.
On Windows, that yields the result I (naively?) expected: compiler warnings about inconsistent linkage declarations.
Ouch.
This is your basic Undocumented X-Platform Macro Hell, and I suppose the Windows build should be #define'ing USE_DL_EXPORT for these subprojects anyway (?), but if I don't hear a good reason for *why* both macros are used on the same name in the same file, I'll be irresistibly tempted to just delete the new DL_IMPORT lines. That is, why would we *ever* use DL_IMPORT on the name of a module init function? They only exist to be exported.
Here's how I arrived at it, but appearantly this doesn't make sense, because Windows has too many linkage options. ;) Compiling with gcc using the -Wmissing-prototypes option causes a warning to be printed if there isn't a prototype at all: cj42289-a(.../linux-beowolf/Modules); gcc -fpic -g -ansi -Wall -Wmissing-prototypes -O2 -I../../Include -I.. -DHAVE_CONFIG_H -c ../../Modules/parsermodule.c ../../Modules/parsermodule.c:2852: warning: no previous prototype for `initparser' I used the DL_IMPORT since that's how all the prototypes in the Python headers are set up. I can either change these to "normal" prototypes (no DL_xxPORT macros), DL_EXPORT prototypes, or remove the prototypes completely, and we'll just have to ignore the warning. If you can write a few sentences explaining each of these macros and when they should be used, I'll make sure they land in the documentation. ;) -Fred -- Fred L. Drake, Jr. <fdrake at beopen.com> BeOpen PythonLabs Team Member
[Tim, gripes about someone putting module init function names in both DL_IMPORT and DL_EXPORT macros] [Fred Drake]
That was me.
My IRC chat buddy Fred? Well, can't get mad at *you*!
On Windows, that yields the result I (naively?) expected: compiler warnings about inconsistent linkage declarations.
Ouch.
Despite that-- as MarkH said later --these macros are as damnably confusing as original sin, that one says "IMPORT" and the other "EXPORT" *may* have been cause to guess they might not play well together when applied to a single name.
... Compiling with gcc using the -Wmissing-prototypes option causes a warning to be printed if there isn't a prototype at all:
Understood, and your goal is laudable. I have a question, though: *all* module init functions use DL_EXPORT today, and just a few days ago *none* of them used DL_IMPORT inside the file too. So how come gcc only warned about two modules? Or does it actually warn about all of them, and you snuck this change into pyexpat and parsermodule while primarily doing other things to them?
I can either change these to "normal" prototypes (no DL_xxPORT macros), DL_EXPORT prototypes,
I already checked that one in.
or remove the prototypes completely, and we'll just have to ignore the warning.
No way. "No warnings" is non-negotiable with me -- but since I no longer get any warnings, I can pretend not to know that you get them under gcc <wink>.
If you can write a few sentences explaining each of these macros and when they should be used, I'll make sure they land in the documentation. ;)
I can't -- that's why I posted for help. The design is currently incomprehensible; e.g., from the PC config.h: #ifdef USE_DL_IMPORT #define DL_IMPORT(RTYPE) __declspec(dllimport) RTYPE #endif #ifdef USE_DL_EXPORT #define DL_IMPORT(RTYPE) __declspec(dllexport) RTYPE #define DL_EXPORT(RTYPE) __declspec(dllexport) RTYPE #endif So if you say "use import", the import macro does set up an import, but the export macro is left undefined (turns out it's later set to an identity expansion in Python.h, in that case). But if you say "use export", both import(!) and export macros are set up to do an export. It's apparently illegal to say "use both", but that has to be deduced from the compiler error that *would* result from redefining the import macro in an incompatible way. And if you say neither, the trail snakes back to an earlier blob of code, where "use import" is magically defined whenever "use export" *isn't* -- but only if MS_NO_COREDLL is *not* defined. And the test of MS_NO_COREDLL is immediately preceded by the comment ... MS_NO_COREDLL (do not test this macro) That covered one of the (I think) four sections in the now 750-line PC config file that defines these things. By the time I look at another config file, my brain is gone. MarkH is right: we have to figure what these things are actually trying to *accomplish*, then gut the code and spell whatever that is in a clear way. Or, failing that, at least a documented way <wink>.
This is your basic Undocumented X-Platform Macro Hell, and I suppose the Windows build should be #define'ing USE_DL_EXPORT for these subprojects anyway (?), but if I don't hear a good reason for *why* both macros are used
This is a mess that should be cleaned up. I take some blame for DL_IMPORT :-( Originally (and still, as far as I can tell), DL_IMPORT really means "Python symbol visible outside the core" - ie, any symbol a dynamic module or embedded application may ever need (documented, or not :-) The "import" part of DL_IMPORT is supposed to be from the _clients_ POV. These apps/extensions are importing these definitions. This is clearly a poor choice of names, IMO, as the macro USE_DL_EXPORT changes the meaning from import to export, which is clearly confusing. DL_EXPORT, on the other hand, seems to have grown while I wasnt looking :-) As far as I can tell: * It is used in ways where the implication is clearly "export this symbol always". * It is used for extension modules, whether they are builtin or not (eg, "array" etc use it. * It behaves differently under Windows than under BeOS, at least. BeOS unconditionally defines it as an exported symbol. Windows only defines it when building the core. Extension modules attempting to use this macro to export them do not work - eg, "winsound.c" uses DL_EXPORT, but is still forced to add "export:initwinsound" to the linker to get the symbol public. The ironic thing is, that in Windows at least, DL_EXPORT is working the exact opposite of how we want it - when it is used for functions built into the core (eg, builting modules), these symbols do _not_ need to be exported, but where it is used on extension modules, it fails to make them public. So, as you guessed, we have the situation that we have 2 macros that given their names, are completely misleading :-( I think that we should make the following change (carefully, of course :-) * DL_IMPORT -> PYTHON_API * DL_EXPORT -> PYTHON_MODULE_INIT. Obviously, the names are up for grabs, but we should change the macros to what they really _mean_, and getting the correct behaviour shouldn't be a problem. I don't see any real cross-platform issues, as long as the macro reflects what it actually means! Shall I check in the large number of files affected now? Over-the-release-manager's-dead-body<wink> ly, Mark.
participants (3)
-
Fred L. Drake, Jr. -
Mark Hammond -
Tim Peters