Re: [Cython] Fwd: Question about how best require compiler options for C sources

2016-04-11 Thread Erik Bray
On Fri, Apr 8, 2016 at 5:49 PM, Nathaniel Smith  wrote:
> Can you give a tiny concrete example? My questions are basic enough that I
> feel like I'm missing something fundamental :-)

Yes, I think you might be missing something, but I'm not sure exactly
where.  In the issue I provided a tiny example which you can see here:

https://gist.github.com/embray/12a67edb82b213217e31f408007898e6

The C code generated by this example currently does not compile on
Windows, because of how Cython uses DL_IMPORT incorrectly.  Regardless
of what it *does* do, Cython should not be using the DL_IMPORT macro
at all actually since that no longer even exists in Python.

> My first question is why you even need this, since AFAIK there are no cases
> where it is correct to have a cython module dllexporting symbols that appear
> in header files. This is what cimport is for, right?

I don't think this has anything to do with cimport.  Could you explain
what you mean?

> My second question is why you would want to do this via the command line,
> when compiling the dll means that you are compiling some cython-generated
> .c, which means that you can put the #define directly in the source code,
> no?

Not necessarily. As you can see in my example the file fooutil.c is
hand-written C code that was not generated by Cython, but which uses a
function in the Cython-generated code.  It includes "foo.h".  In
principle you're right--the hand-written C code could set the proper
#defines but it would have to do so *before* including "foo.h".  It's
not very obvious that this would be needed.  Most other code I've seen
that addresses this issue--including cpython itself--do so by passing
an appropriate define to the compiler via the command-line, and that
seems the clearest to me.

Best,
Erik

> On Apr 8, 2016 5:35 AM, "Erik Bray"  wrote:
>>
>> Hi all,
>>
>> I'd like to call attention to an issue I've been looking into for the
>> past couple days:
>>
>> https://github.com/cython/cython/pull/360
>>
>> To summarize the discussion, when building DLLs for Windows, functions
>> that should be exported by that DLL must be marked
>> __declspec(dllexport) in their declaration.  However, when using the
>> same header file in a project that links to that DLL the same function
>> must be declared __declspec(dllimport).
>>
>> It's common practice to have a macro for this, whose value is
>> controlled by whether or not a macro (often called something like
>> "DLL_EXPORT").  When compiling the DLL we would define -DDLL_EXPORT to
>> output __declspec(dllexport).  Otherwise it outputs
>> __declspec(dllimport).
>>
>> Cython currently handles this with such a macro called DL_IMPORT which
>> comes from Python. However, this macro was deprecated some time ago,
>> and is removed in current Python 3 versions.  So Cython must replace
>> it with its own.
>>
>> I'm working on a patch for this--to reduce confusion the macro is
>> named specifically for the Cython module it's associated with.  For
>> example, for a Cython module named "foo.bar" there are two macros
>> DLL_EXPORT__foo__bar and EXPORT__foo__bar.  If the latter is defined
>> then the former outputs dllexport, otherwise it outputs dllimport.
>> I've attached the patch in progress.
>>
>> I'm open to comment on this, but where I'm stuck now is that in order
>> for the "foo.bar" module to be compiled correctly it needs
>> EXPORT__foo__bar to be defined at compile time.  And it's not clear to
>> me what the best way is for the Cython compiler to pass down options
>> that are passed to the C/C++ compiler.  In general the best way would
>> be to attach this to the define_macros attribute of the associated
>> distutils/setuptools Extension object and let the distutils compiler
>> class generate the right compiler options.  But it's not clear to me
>> from Cython's internals where the best place to do that would be.
>>
>> Thanks,
>> Erik
>>
>> ___
>> cython-devel mailing list
>> cython-devel@python.org
>> https://mail.python.org/mailman/listinfo/cython-devel
>>
>
> ___
> cython-devel mailing list
> cython-devel@python.org
> https://mail.python.org/mailman/listinfo/cython-devel
>
___
cython-devel mailing list
cython-devel@python.org
https://mail.python.org/mailman/listinfo/cython-devel


Re: [Cython] Fwd: Question about how best require compiler options for C sources

2016-04-11 Thread Nathaniel Smith
On Apr 11, 2016 04:18, "Erik Bray"  wrote:
>
> On Fri, Apr 8, 2016 at 5:49 PM, Nathaniel Smith  wrote:
> > Can you give a tiny concrete example? My questions are basic enough
that I
> > feel like I'm missing something fundamental :-)
>
> Yes, I think you might be missing something, but I'm not sure exactly
> where.  In the issue I provided a tiny example which you can see here:
>
> https://gist.github.com/embray/12a67edb82b213217e31f408007898e6
>
> The C code generated by this example currently does not compile on
> Windows, because of how Cython uses DL_IMPORT incorrectly.  Regardless
> of what it *does* do, Cython should not be using the DL_IMPORT macro
> at all actually since that no longer even exists in Python.

Sure.

For that example, the correct thing to do is to *not* export the function.

Backing up, to make sure we're on the same page: There are three levels of
symbol visibility in C: file-internal, shared library internal (different
.c files that make up the library can see it, but users of the shared
library can't see it), and shared library exported (everyone can see it;
can also carry other consequences, e.g. on Linux then internal calls will
become noticeably slower, and it becomes possible for weird symbol
interposition issues to occur). So the rule of thumb is to make everything
as private as you can get away with.

Making this more interesting:
- vanilla C only includes 2 ways to mark symbol visibility, which is not
enough to make a 3-way distinction. Hence the need for an extra attribute
thingummy.
- everyone agrees that symbols marked 'static' should be file-internal, but
different platforms disagree about what should happen if the extra
attribute thingummy is missing.

So on Windows, the convention is:
'static' -> file internal
no marking -> shared library internal
'dllexport' -> public

And on Linux it's:
'static' -> file internal
'visibility (hidden)' -> shared library internal
no marking -> public

It's generally agreed that Linux got this wrong and that you should always
use '-fvisibility=hidden' to switch it to the windows style, but cython
doesn't control compiler options and thus should probably generate code
that works correctly regardless of such compiler settings. Fortunately,
Linux does provide some markings to explicitly make things public: you can
mark a symbol 'visibility (default)' (which means public), or you can use
the dllexport syntax, just like Windows, because gcc is helpful like that.

OTOH, windows is annoying because of this dllimport thing that started this
whole thread: on other systems just marking symbols as extern is enough to
handle both shared-object-internal and shared-library-exported symbols, and
the linker will sort it out. On Windows, you have to explicitly distinguish
between these. (And annoyingly, if you accidentally leave out the dllimport
making on functions then it will use some fallback hack that works but
silently degrades performance; on other symbols it just doesn't work, and
ditto for if you use it when it isn't needed.)

So final conclusion: for non-static symbols, cython should first decide
whether they are supposed to be shared-library-internal or actually
exported from the shared library.

For shared-library-internal symbols: their definition should be marked
'visibility(hidden)' on Linux, and unmarked on Windows. This is easy using
some preprocessor gunk. (Or maybe simplest is: marked that everywhere
except if using msvc, because I think everyone else will understand
'visibility (hidden)' even if it's a no op.) Their declaration in the
header file should just be 'extern' everywhere.

For shared-library-exported symbols: I am dubious about whether cython
should even support these at all. But if it does, then the definitions
should be marked 'dllexport' (no macro trickery needed, because everyone
understands this syntax), and their declaration in the header file needs
some extra hack that is the subject of this thread.

Now, back to your example: Here the caller and callee are both compiled
into the same shared library, so you don't want dllexport/dllimport at all,
you just want a shared-library-internal symbol, which as we see is much
easier.

NumPy also ran into some problems with this in our experiments with using
cython internally. Our temporary solution was to use the preprocessor to
monkeypatch DL_IMPORT into expanding to the appropriate
shared-library-internal thing :-).

> > My first question is why you even need this, since AFAIK there are no
cases
> > where it is correct to have a cython module dllexporting symbols that
appear
> > in header files. This is what cimport is for, right?
>
> I don't think this has anything to do with cimport.  Could you explain
> what you mean?

We only need to solve the dllimport issue if we want to support
shared-library-exported symbols from cython extensions. This is only useful
if you have different extensions that are directly linking to each other
using the platform linker. But this simply 

Re: [Cython] Fwd: Question about how best require compiler options for C sources

2016-04-11 Thread Erik Bray
On Mon, Apr 11, 2016 at 2:51 PM, Nathaniel Smith  wrote:
> Now, back to your example: Here the caller and callee are both compiled into
> the same shared library, so you don't want dllexport/dllimport at all, you
> just want a shared-library-internal symbol, which as we see is much easier.

Sorry, I'll respond more to your (helpfully detailed and precise)
message in a second.  But something I wanted to point out is that my
example is incomplete and I should have arranged a more complete
example.  In this case I really do want the symbol "hello" to be
exported by the DLL, as well as be understood between translation
units making up the same library.  A more complete example would have
shown a separate library which links with "foo" and uses the "hello"
function in it.

Yes, it's arguable that exporting anything more than then initmodule
function from a Python extension module is not best practice, but the
possibility should not be ruled out either.

So I think later on you hit correctly on the deeper problem, which is
that Cython currently doesn't have a great way to distinguish between
intra-library visibility and *inter*-library visibility.

And if both are needed then some DL_IMPORT-like macro is needed that
sets the visibility for a symbol correctly depending on the context in
which it's being used. (And yes, this is not a problem on *nix, but it
is on Windows due to the way __declspec(dllimport) causes name
mangling :(

Thanks,
Erik
___
cython-devel mailing list
cython-devel@python.org
https://mail.python.org/mailman/listinfo/cython-devel


Re: [Cython] Fwd: Question about how best require compiler options for C sources

2016-04-11 Thread Erik Bray
On Mon, Apr 11, 2016 at 2:51 PM, Nathaniel Smith  wrote:
> On Apr 11, 2016 04:18, "Erik Bray"  wrote:
>>
>> On Fri, Apr 8, 2016 at 5:49 PM, Nathaniel Smith  wrote:
>> > Can you give a tiny concrete example? My questions are basic enough that
>> > I
>> > feel like I'm missing something fundamental :-)
>>
>> Yes, I think you might be missing something, but I'm not sure exactly
>> where.  In the issue I provided a tiny example which you can see here:
>>
>> https://gist.github.com/embray/12a67edb82b213217e31f408007898e6
>>
>> The C code generated by this example currently does not compile on
>> Windows, because of how Cython uses DL_IMPORT incorrectly.  Regardless
>> of what it *does* do, Cython should not be using the DL_IMPORT macro
>> at all actually since that no longer even exists in Python.
>
> Sure.
>
> For that example, the correct thing to do is to *not* export the function.

So as I wrote in my previous message, my example was incomplete.  But
indeed if the intent was *only* to share the declaration between TUs
of the same library then I agree the *most* correct thing would be to
not use dllexport. Unfortunately there isn't currently a way in Cython
to make this distinction.

> Backing up, to make sure we're on the same page:

Yep, I agree with your analysis that follows, and it's helpful to have
all the cases laid out in one place, so thanks for that!

There are three levels of
> symbol visibility in C: file-internal, shared library internal (different .c
> files that make up the library can see it, but users of the shared library
> can't see it), and shared library exported (everyone can see it; can also
> carry other consequences, e.g. on Linux then internal calls will become
> noticeably slower, and it becomes possible for weird symbol interposition
> issues to occur). So the rule of thumb is to make everything as private as
> you can get away with.
>
> Making this more interesting:
> - vanilla C only includes 2 ways to mark symbol visibility, which is not
> enough to make a 3-way distinction. Hence the need for an extra attribute
> thingummy.
> - everyone agrees that symbols marked 'static' should be file-internal, but
> different platforms disagree about what should happen if the extra attribute
> thingummy is missing.
>
> So on Windows, the convention is:
> 'static' -> file internal
> no marking -> shared library internal
> 'dllexport' -> public
>
> And on Linux it's:
> 'static' -> file internal
> 'visibility (hidden)' -> shared library internal
> no marking -> public
>
> It's generally agreed that Linux got this wrong and that you should always
> use '-fvisibility=hidden' to switch it to the windows style, but cython
> doesn't control compiler options and thus should probably generate code that
> works correctly regardless of such compiler settings. Fortunately, Linux
> does provide some markings to explicitly make things public: you can mark a
> symbol 'visibility (default)' (which means public), or you can use the
> dllexport syntax, just like Windows, because gcc is helpful like that.
>
> OTOH, windows is annoying because of this dllimport thing that started this
> whole thread: on other systems just marking symbols as extern is enough to
> handle both shared-object-internal and shared-library-exported symbols, and
> the linker will sort it out. On Windows, you have to explicitly distinguish
> between these. (And annoyingly, if you accidentally leave out the dllimport
> making on functions then it will use some fallback hack that works but
> silently degrades performance; on other symbols it just doesn't work, and
> ditto for if you use it when it isn't needed.)

Yep. Agreed with all of the above.

> So final conclusion: for non-static symbols, cython should first decide
> whether they are supposed to be shared-library-internal or actually exported
> from the shared library.
>
> For shared-library-internal symbols: their definition should be marked
> 'visibility(hidden)' on Linux, and unmarked on Windows. This is easy using
> some preprocessor gunk. (Or maybe simplest is: marked that everywhere except
> if using msvc, because I think everyone else will understand 'visibility
> (hidden)' even if it's a no op.) Their declaration in the header file should
> just be 'extern' everywhere.
>
> For shared-library-exported symbols: I am dubious about whether cython
> should even support these at all. But if it does, then the definitions
> should be marked 'dllexport' (no macro trickery needed, because everyone
> understands this syntax), and their declaration in the header file needs
> some extra hack that is the subject of this thread.

I understand your doubts here, but for the purpose of discussion let's
just assume that it should be supported? :)

And yes, the issue that the header file needs some hacky
context-dependent declarations.  A possible alternative, which in fact
is exactly the work-around I'm using right now, would be for Cython to
generate two headers.  In the case of my example the

Re: [Cython] Fwd: Question about how best require compiler options for C sources

2016-04-11 Thread Nathaniel Smith
On Apr 11, 2016 06:23, "Erik Bray"  wrote:
>
> On Mon, Apr 11, 2016 at 2:51 PM, Nathaniel Smith  wrote:
> > Now, back to your example: Here the caller and callee are both compiled
into
> > the same shared library, so you don't want dllexport/dllimport at all,
you
> > just want a shared-library-internal symbol, which as we see is much
easier.
>
> Sorry, I'll respond more to your (helpfully detailed and precise)
> message in a second.  But something I wanted to point out is that my
> example is incomplete and I should have arranged a more complete
> example.  In this case I really do want the symbol "hello" to be
> exported by the DLL, as well as be understood between translation
> units making up the same library.  A more complete example would have
> shown a separate library which links with "foo" and uses the "hello"
> function in it.
>
> Yes, it's arguable that exporting anything more than then initmodule
> function from a Python extension module is not best practice, but the
> possibility should not be ruled out either.
>
> So I think later on you hit correctly on the deeper problem, which is
> that Cython currently doesn't have a great way to distinguish between
> intra-library visibility and *inter*-library visibility.
>
> And if both are needed then some DL_IMPORT-like macro is needed that
> sets the visibility for a symbol correctly depending on the context in
> which it's being used. (And yes, this is not a problem on *nix, but it
> is on Windows due to the way __declspec(dllimport) causes name
> mangling :(

This is highly tangential to the main conversation, but FYI and in the
general interests of demystifying this stuff: the reason for all this
rigmarole on Windows is that dllimport doesn't just cause name mangling, it
causes *type* mangling. The way windows symbol relocations work, is that
you can only import pointers. So code like

  __declspec(dllimport) extern void f(...);
  __declspec(dllimport) extern int myvalue;

is syntactic sugar for something like:

  // pointer that will be filled in by loader
  void (*__imp_f)(...);
  // desugar direct calls into indirect calls
  #define f(...) (*__imp_f)(...)

  // similar
  int *__imp_myint;
  #define myint (*__imp_myint)

...except that (a) instead of using the preprocessor to perform the
substitution, it happens in the compiler frontend, so it can correctly
follow scoping rules and things that the preprocessor can't, and (b) the
linker will also automagically generate a function like

  void f(...) {
  return (*__imp_f)(...);
  }

So there shouldn't still be any mentions of 'f' in the resulting file --
they should all be replaced by mentions of (*__imp_f) -- but just in case
we missed any your code will still work, albeit at the cost of some icache
pollution and an extra indirect jump at every call.

Note in particular that this __imp_ nonsense *isn't* an approximation on my
part, there really will be a shared-library-internal symbol called
__imp_whatever whose value is a pointer that gets filled in my the loader.
(Except possibly I got my underscores wrong -- on phone so too lazy to
check.) You could literally write the code I wrote above with the #define's
and it would actually work on windows...

-n
___
cython-devel mailing list
cython-devel@python.org
https://mail.python.org/mailman/listinfo/cython-devel


Re: [Cython] Fwd: Question about how best require compiler options for C sources

2016-04-11 Thread Jeroen Demeyer

On 2016-04-11 15:23, Erik Bray wrote:

In this case I really do want the symbol "hello" to be
exported by the DLL, as well as be understood between translation
units making up the same library.


Are you really sure that you want this? I doubt that this is supported 
on OS X: on OS X, there are two kinds of files: shared libraries (with 
.dylib extension) and loadable modules or bundles (usually with .so 
extension but officially with .bundle extension).


C extensions for Python are compiled as a loadable module and I don't 
think you can link against these. See 
http://stackoverflow.com/questions/2339679/what-are-the-differences-between-so-and-dylib-on-osx


Some details in the above might be wrong, but I remember running into 
this issue in some early version of cysignals.


Jeroen.
___
cython-devel mailing list
cython-devel@python.org
https://mail.python.org/mailman/listinfo/cython-devel


Re: [Cython] Fwd: Question about how best require compiler options for C sources

2016-04-11 Thread Ian Henriksen
On Mon, Apr 11, 2016 at 7:46 AM Erik Bray  wrote:

> On Mon, Apr 11, 2016 at 2:51 PM, Nathaniel Smith  wrote:
> > On Apr 11, 2016 04:18, "Erik Bray"  wrote:
> >>
> >> On Fri, Apr 8, 2016 at 5:49 PM, Nathaniel Smith  wrote:
> >> > Can you give a tiny concrete example? My questions are basic enough
> that
> >> > I
> >> > feel like I'm missing something fundamental :-)
> >>
> >> Yes, I think you might be missing something, but I'm not sure exactly
> >> where.  In the issue I provided a tiny example which you can see here:
> >>
> >> https://gist.github.com/embray/12a67edb82b213217e31f408007898e6
> >>
> >> The C code generated by this example currently does not compile on
> >> Windows, because of how Cython uses DL_IMPORT incorrectly.  Regardless
> >> of what it *does* do, Cython should not be using the DL_IMPORT macro
> >> at all actually since that no longer even exists in Python.
> >
> > Sure.
> >
> > For that example, the correct thing to do is to *not* export the
> function.
>
> So as I wrote in my previous message, my example was incomplete.  But
> indeed if the intent was *only* to share the declaration between TUs
> of the same library then I agree the *most* correct thing would be to
> not use dllexport. Unfortunately there isn't currently a way in Cython
> to make this distinction.
>
> > Backing up, to make sure we're on the same page:
>
> Yep, I agree with your analysis that follows, and it's helpful to have
> all the cases laid out in one place, so thanks for that!
>
> There are three levels of
> > symbol visibility in C: file-internal, shared library internal
> (different .c
> > files that make up the library can see it, but users of the shared
> library
> > can't see it), and shared library exported (everyone can see it; can also
> > carry other consequences, e.g. on Linux then internal calls will become
> > noticeably slower, and it becomes possible for weird symbol interposition
> > issues to occur). So the rule of thumb is to make everything as private
> as
> > you can get away with.
> >
> > Making this more interesting:
> > - vanilla C only includes 2 ways to mark symbol visibility, which is not
> > enough to make a 3-way distinction. Hence the need for an extra attribute
> > thingummy.
> > - everyone agrees that symbols marked 'static' should be file-internal,
> but
> > different platforms disagree about what should happen if the extra
> attribute
> > thingummy is missing.
> >
> > So on Windows, the convention is:
> > 'static' -> file internal
> > no marking -> shared library internal
> > 'dllexport' -> public
> >
> > And on Linux it's:
> > 'static' -> file internal
> > 'visibility (hidden)' -> shared library internal
> > no marking -> public
> >
> > It's generally agreed that Linux got this wrong and that you should
> always
> > use '-fvisibility=hidden' to switch it to the windows style, but cython
> > doesn't control compiler options and thus should probably generate code
> that
> > works correctly regardless of such compiler settings. Fortunately, Linux
> > does provide some markings to explicitly make things public: you can
> mark a
> > symbol 'visibility (default)' (which means public), or you can use the
> > dllexport syntax, just like Windows, because gcc is helpful like that.
> >
> > OTOH, windows is annoying because of this dllimport thing that started
> this
> > whole thread: on other systems just marking symbols as extern is enough
> to
> > handle both shared-object-internal and shared-library-exported symbols,
> and
> > the linker will sort it out. On Windows, you have to explicitly
> distinguish
> > between these. (And annoyingly, if you accidentally leave out the
> dllimport
> > making on functions then it will use some fallback hack that works but
> > silently degrades performance; on other symbols it just doesn't work, and
> > ditto for if you use it when it isn't needed.)
>
> Yep. Agreed with all of the above.
>
> > So final conclusion: for non-static symbols, cython should first decide
> > whether they are supposed to be shared-library-internal or actually
> exported
> > from the shared library.
> >
> > For shared-library-internal symbols: their definition should be marked
> > 'visibility(hidden)' on Linux, and unmarked on Windows. This is easy
> using
> > some preprocessor gunk. (Or maybe simplest is: marked that everywhere
> except
> > if using msvc, because I think everyone else will understand 'visibility
> > (hidden)' even if it's a no op.) Their declaration in the header file
> should
> > just be 'extern' everywhere.
> >
> > For shared-library-exported symbols: I am dubious about whether cython
> > should even support these at all. But if it does, then the definitions
> > should be marked 'dllexport' (no macro trickery needed, because everyone
> > understands this syntax), and their declaration in the header file needs
> > some extra hack that is the subject of this thread.
>
> I understand your doubts here, but for the purpose of discussion let's
> just assume that i

Re: [Cython] Fwd: Question about how best require compiler options for C sources

2016-04-11 Thread Ian Henriksen
On Mon, Apr 11, 2016 at 11:50 AM Ian Henriksen <
insertinterestingnameh...@gmail.com> wrote:

> To answer the original question about define macros, it appears that the
> canonical
> way to pass preprocessor defines through distutils is to use the
> define_macros
> keyword when constructing your Extension class. You should also be able to
> do
> this within a Cython source file by including a directive like:
>
> # distutils: define_macros = MY_DEFINE, MY_DEFINE_2=2
>
> Unfortunately, it looks like there's a bug in that that's making it so
> that these
> macros are undef'ed rather than being defined, so, for now, just pass the
> appropriate flags to your Extension object.
>
>
Small update on this, it looks like the issue with undef/define only
applies when a
define is specified this way without a value, so I either haven't gotten
the syntax quite
right, or that's not supported yet. Specifying an actual value for the
macro works fine.

Best,
Ian Henriksen
___
cython-devel mailing list
cython-devel@python.org
https://mail.python.org/mailman/listinfo/cython-devel