How does one get from "ImportError: DLL load failed:..." to a culprit .dll and symbol?

John Machin sjmachin at lexicon.net
Tue Feb 24 00:01:28 EST 2009


On Feb 24, 2:54 pm, Chris Cormie <ccor... at aussiemail.com.au> wrote:
> Mark Hammond wrote:
> > On 23/02/2009 11:41 PM, Chris Cormie wrote:
>
> >>> If that not-very-technical description [all I've ever needed] doesn't
> >>> help, you'll need to read the DW help file (HTFF1K) or wait till
> >>> someone who knows what they are doing comes along :-)
>
> >> LOL, I am that person :p
>
> > LOL sounds right!
>
> >> How do you get *Python* to tell you the dll and the problem symbol? Not
> >> external tools, Python. Python at a low level is calling LoadLibrary and
> >> GetProcAddress to resolve symbols and the call fails.
>
> > It is the LoadLibrary that is failing; it should be obvious that if it
> > was a simple GetProcAddress that was failing, Python would simply throw
> > an exception rather than displaying the ugly dialog box you see.
>
> > The problem is that some *other* DLL in the chain of dependencies is
> > failing to load; please re-adjust your perceptions of your own knowledge
> > and re-read John's initial response - if you follow his instructions
> > that should all become quite obvious.
>
> > Mark
>
> I think an example would help rather than me jabbering on about
> LoadLibary/GetProcAddress .
>
> It really is a case of Python loads module x depending on DLL y that is
> missing symbol z, yet the error message is just "load x failed" when in
> theory it could be "load x failed: y doesn't have z".
>
> However I think I am confusing people (and myself!) by assuming it's

Don't assume; read the [open] source code; see below.

> always as explicit as a LoadLibary/GetProcAddress sequence that is
> failing when people see this error.
>
> Let me explain by giving the specific example case I have to hand.
> I originally got on to this class of opaque runtime errors caused by
> missing symbols through building the pycURL extension on MinGW. As of
> Python 2.6, Python links against the new msvcr90.dll C Runtime. MinGW
> maintains a set of .a files for system DLLs including the C Runtime.
> When building pycURL naturally I want to link against libmsvcr90.a so
> Python 2.6 and pycURL are using the same C Runtime. Problem was, MinGW's
>   .a was wrong: it exports symbols that msvcr90.dll does not in fact
> possess. Building pycURL with the faulty libmsvcr90.a causes the opaque
> error message: "ImportError: DLL load failed"
>
> I think Gabriel's got the part of the answer: she said  "it isn't Python
> who's trying to load the symbol - the *only* symbol that Python attempts
> to import itself is "initFOO" from FOO.pyd"
>
> So my next question is: given the above missing-symbol problem, is the
> system able/willing to report the bad symbol reference in the .pyd when
> Python attempts to import initFOO?

My reading of the Python 2.6.1 version of dynload_win.c tells me that:

1. It uses LoadLibraryEx() to attempt to load the pyd given its full
pathname

2. If that fails, it gets the Windows error code using GetLastError()

3. It gets the Windows message text using FormatMessage()

4. It assembles the message as "DLL load failed: " plus the Windows
message text (less any trailing "\r\n").

Note that if the pyd load succeeds, it rummages in memory to find the
pythonxx.dll used by the pyd so that it can be checked for
consistency. Then and only then it uses GetProcAddress() to get the
address of the initFOO function.

Do you know a way of getting more info out of Windows than GetLastError
()?



More information about the Python-list mailing list