This is the mail archive of the
gcc-help@gcc.gnu.org
mailing list for the GCC project.
Re: dllexport and inline methods
- From: Geoff Worboys <geoff at telesiscomputing dot com dot au>
- To: gcc-help at gcc dot gnu dot org
- Date: Mon, 8 Apr 2013 12:27:43 +1000
- Subject: Re: dllexport and inline methods
- References: <7610142819 dot 20130406143754 at telesiscomputing dot com dot au>
I wrote:
[...]
> class __declspec(dllexport) A {
> public:
> int fa() { return m; }
> int ga();
> private:
> int m{0};
> };
> class __declspec(dllexport) B {
> public:
> int fb();
> int gb();
> private:
> int m{0};
> };
> inline int B::fb() { return m; }
>
> class C {
> public:
> int fc() { return m; }
> __declspec(dllexport) int gc();
> private:
> int m{0};
> };
[...]
> Notice that inline methods for class A and class B are NOT
> being inlined inside the library (and the compiler does tell us
> why in the case of B::fb()).
[...]
For those of us that would like to be able to build optimised
shared libraries under Windows, without having to rewrite all
code to look like class C above, I think I have found a work-
around.
An off-list reply to my query suggested I play with .def files.
I had previously discarded using def files as being too hard
with C++. But it turns out not to be so hard.
First step:
Stop using dllexport and dllimport with mingw/gcc. Leave
your macros in place so they will work with msvc builds, but
under gcc set to them to blank.
Add this to your linker commands: -Wl,--export-all-symbols
(the -Wl, prefix needed if passing through gcc/g++)
Make sure your build produces its own def file:
-Wl,--output-def=mylib.def
This works with my current project, and it seems that this step
is all that is necessary - just not very neat. I expect it
will be easier to leave this configuration in place while the
library is still under active development.
gcc happily compiles the library, including inlining where
it can. I ran across a few instances where using class A style
code did not resolve when using the library. I moved the few
instances of those to class B (out-of-class inline) and those
problems went away. (No idea why, I thought class A and class
B should be effectively identical.)
QUESTION: Does anyone know of any down-side to using
--export-all-symbols other than the increase in interface
size (and resulting startup impact)?
Second step:
I just tried out the next step in the process, which is to take
the .def file produced above (by the --output-def) and filter
it to include only the necessary symbols.
You can then use the filtered result to rebuild your libraries
using -Wl,mydef.def in place of -Wl,--export-all-symbols. The
result being a smaller and more efficient interface (we hope).
I'd like to automate the .def file filtering, which should be
easy enough on the first library using namespaces, but I'm
creating a project of multiple libraries all of which work over
the same namespace so filtering could get more difficult. But
it's still easier to filter the result from step one than to
write a new one from scratch.
I'm guessing other complications may arise, but I'm hoping that
they can be resolved. The above, so far, seems to be working
with the two libraries on my current project - about 30 classes
or maybe a bit more. So it looks promising. I have read that
strange things may happen with exception classes if you don't
get the export exactly right, so I have more testing to do.
I don't know what dllexport is really doing inside gcc, it
appears to have taken on a meaning above that of "export this
this symbol" and gives peculiar attributes to functions that
are not always appropriate.
--
Geoff Worboys
Telesis Computing Pty Ltd