On Tuesday, 20 January 2015 at 12:23:32 UTC, Benjamin Thaut wrote:
I'm currently working on Windows DLL support which has stronger
rules than linux shared objects for which symbols actually get
exported from a shared library. But as we want to replicate the
same behaviour on linux using symbol visibility (e.g. gcc 4
-fVisibility=hidden) this issue also applies to linux once
implemented.
Currently export means two things:
- the symbol is publicy accessible (same as public)
- the symbol will be accisble across shared library boundaries
This has the following issue:
export void templateFunc(T)()
{
someHelperFunc();
}
private void someHelperFunc()
{
}
And you don't even have to go into phobos to hit this problem.
It is already in druntime see core.time.FracSec._enforceValid
This works with the current linux shared objects because they
simply export all symbols. But once only symbols with export
get exported this breaks.
The problem here is that you don't want to make
someHelperFunc() export because that would mean users could
call it directly, but you want it to be available for cross
shared library calls. The cross shared library call happens if
a template is instanced from a different shared library /
executable than the module it was originally located in.
There are two solutions for this.
1) Given that export is transitive (that means if a struct or
class is declared export every member that is _not_ private
will be accessible across shared library boundaries. This
behaviour is required to make the export protection level work
on windows)
You can now do the following:
export struct SomeStruct
{
static public void templateFunc(T)()
{
someHelperFunc();
}
static package void someHelperFunc()
{
}
}
Because of the transitivity someHelperFunc will be exported but
still not be callable by the user directly. This can be used to
fix the issue in core.time but may not be so well suited if you
want the template to be on module level instead of nesting it
into a struct.
2) Make export an attribute. If export is no longer an
protection level but instead an attribute this issue can easily
be solved by doing.
export public void templateFunc(T)()
{
someHelperFunc();
}
export private void someHelperFunc()
{
}
But this would require grammar changes. Which are generally
avoided if possible.
There would be a third option, which I rather avoid. Doing a
"pramga(forceExport)" or something like that.
My implementation, which I ran into this issue with, currently
usses approach 1. What do you think how this sould be solved?
Walter: What was the general idea behind export when you
designed it, and how can it be used to solve this problem?
Kind Regards
Benjamin Thaut
Just as heads up in case D ever comes to Aix, I don't know how it
looks like nowadays, but Aix back in 2000 used to be have similar
behavior to Windows.
The .def files in Windows were .exp (I think) files on Aix.
--
Paulo