External declarations without headers fail with mingw-w64

135 views
Skip to first unread message

Ian Henriksen

unread,
Jan 22, 2015, 5:31:40 PM1/22/15
to cython...@googlegroups.com
I have a workaround for this, but I'm reporting it anyway so it can be
fixed at some point and so that it doesn't confuse anyone else later on.

External declarations, when they are done in Cython without referencing
headers, fail when using mingw-w64 on windows.
The failure only occurs when using an external declaration of the form:

cdef extern int foo()

Writing a header that contains the proper function
declaration and using a declaration of the form

cdef extern from "myfunc.h":
    int foo()

I came across this issue when working with some existing Fortran code.
My goal was to load a function directly from a compiled library
without having to write the corresponding header.

The first type of declaration works perfectly well on Linux, but fails on Windows.
I use the Anaconda Python distribution with the mingw-w64 compilers.

The attached zipped folder contains a minimal example showing what
works and what doesn't.

The error this example gives is:

build\temp.win-amd64-2.7\Release\cython_cadd.o:cython_cadd.c:(.text+0x5c4):
undefined reference to `__imp_cadd'

I'm more than a little lost as to what it is that causes this though.
I have searched through the cython generated c file, the preprocessed file, and
a disassembled unlinked version of the code and am still uncertain of what is going on.
There doesn't seem to be any sort of reference to any such function anywhere.
My suspicion is that it has something to do with the DL_IMPORT
macro not working properly.
Any thoughts?

Thanks!
- Ian Henriksen
cadd.zip

Ian Henriksen

unread,
Jan 24, 2015, 2:06:21 AM1/24/15
to cython...@googlegroups.com
I figured out what was going on here.
The DL_IMPORT macro was expanding to code that loaded the external function
from a dll. If I compiled a dll and used that, it worked fine.
To the best of my knowledge, that is the needed fix, but feedback is
always welcome.

Robert Bradshaw

unread,
Jan 24, 2015, 3:47:37 AM1/24/15
to cython...@googlegroups.com
I'm no windows expert, but doesn't this negatively impact people who
are loading such symbols via a dll?
> --
>
> ---
> You received this message because you are subscribed to the Google Groups
> "cython-users" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to cython-users...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

Ian Henriksen

unread,
Jan 24, 2015, 1:49:38 PM1/24/15
to cython...@googlegroups.com
Unfortunately, I'm not an expert at this either.
It would be really helpful if someone with more experience
with dll interfaces could verify that this is correct.

Here's what I've found online thus far:
and
which both seem to imply that the identifier emitted by the macro
is not necessary unless the function is to be accessed through
the dll interface. Using the dll interface does supposedly allow
for the function to be loaded more quickly though.

Here are a few other related things I've been able to verify:

This macro is not present in Python 3, so the __attribute__((dllimport)) specifier is not emitted
when the macro expands. After macros have been applied, the declaration is a plain extern declaration.

Linking against a function declared without the macro, even if it is included in a dll, works fine with mingw.
(It would be great if someone could confirm that on msvc as well).

In reading the code in Cython that generates these lines, I've noticed that
the fact that the DL_IMPORT and DL_EXPORT macros are no-ops in Python 3
is effecting the use of public declarations as well. It appears that the intent
was to make public functions available as a part of a dll interface, but that isn't the
case with Python 3. That makes me think it may be better to either remove calls
to these macros entirely or redefine them in the preamble for Cython files.


For what it's worth, I find the version without the macro closer to what I'd expect
Cython to output for an external declaration. When I write

cdef extern int foo(int a, int b)

I expect C code of the form

extern int foo(int, int);

and not (after macro expansion)

extern __attribute__((dllimport)) int foo(int, int);

The latter may load the function faster, but it requires that the
external function come from a dll and not a generic object file.

Robert Bradshaw

unread,
Jan 24, 2015, 7:53:05 PM1/24/15
to cython...@googlegroups.com
These were clearly put in for a reason--I know they're no-ops on
everything but Windows so we should wait for a Windows expert or two
to chime in before deleting them.

Ian Henriksen

unread,
Jan 24, 2015, 7:58:52 PM1/24/15
to cython...@googlegroups.com
Yep, that makes sense. I'd really like to hear from an expert on this too.
Reply all
Reply to author
Forward
0 new messages