On Apr 11, 2016 06:23, "Erik Bray" <erik.m.b...@gmail.com> wrote: > > On Mon, Apr 11, 2016 at 2:51 PM, Nathaniel Smith <n...@vorpus.org> 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