Thread overview
Request: "noexport" attribute
Jun 07, 2005
Michael Butscher
Jun 07, 2005
Uwe Salomon
Jun 07, 2005
Vathix
Jun 08, 2005
Michael Butscher
Jun 07, 2005
Chris Sauls
Jun 09, 2005
Michael Butscher
June 07, 2005
Hi,

the problem I want to solve is that some functions should be exported to a DLL (or not) based on a version identifier. This probably could be done also by editing the .def file but would be rather inconvenient.


Example:

----------

version(DLL_C)   // If we want a DLL interface for C
{
  export:
  extern(C):
}

int forC_aaa()
{...}

int forC_bbb()
{...}

noexport:  // Stop exporting
extern(D):  // Stop C linkage



int helper()  // Never exported
{...}



version(DLL_D)   // If we want a DLL interface for D
{
  export:
}

int aaa()
{...}

int bbb()
{...}

noexport:  // Stop exporting

----------


It would be nice also if it could be written this way:

version(DLL_D) {export} int aaa()

But maybe hard to implement.



Michael
June 07, 2005
> version(DLL_C)   // If we want a DLL interface for C
> {
>   export:
>   extern(C):
> }

AFAIK, this will not work as you expect! version() is not the same as #ifdef and friends, where you "include" something. The scope of export: and extern: ends at the closing brace! Anything after version() will have the normal D linkage.

Ciao
uwe
June 07, 2005
On Tue, 07 Jun 2005 15:30:14 -0400, Uwe Salomon <post@uwesalomon.de> wrote:

>> version(DLL_C)   // If we want a DLL interface for C
>> {
>>   export:
>>   extern(C):
>> }
>
> AFAIK, this will not work as you expect! version() is not the same as #ifdef and friends, where you "include" something. The scope of export: and extern: ends at the closing brace! Anything after version() will have the normal D linkage.
>
> Ciao
> uwe

Sometimes { } doesn't introduce a new scope, depending on the statement. In this case I don't think it does and so it should work how he is using it.
June 07, 2005
Since 'export' is a protection attribute, you can end any 'export:' attribute-statement by introducing a new protection attribute, such as 'public'.  In other words:

# version(DLL_C) {
#   export:
#   extern(C):
# }
#
# int forC_aaa() { ... }
# int forC_bbb() { ... }
#
# public:
# extern(D): // default is D, but it may be good to be explicit here
#
# int helper() { ... }
#
# version(DLL_D) {
#   export:
# }
#
# int aaa() { ... }
# int bbb() { ... }
#
# public:


> It would be nice also if it could be written this way:
> 
> version(DLL_D) {export} int aaa()
> 
> But maybe hard to implement.

Maybe the 'alias' statement could be given a new case for attribute symbols...  so you could do something like:

# version (DLL_D) { alias export a_AttrProtection; }
# else            { alias public a_AttrProtection; }
#
# a_AttrProtection int aaa() { ... }

-- Chris Sauls
June 08, 2005
Uwe Salomon wrote:
> > version(DLL_C)   // If we want a DLL interface for C
> > {
> >   export:
> >   extern(C):
> > }
> 
> AFAIK, this will not work as you expect! version() is not the same as #ifdef and friends, where you "include" something. The scope of export: and extern: ends at the closing brace! Anything after version() will have the normal D linkage.
> 
> Ciao
> uwe


I tried it and it works (tested with DMD 0.124).


Michael
June 09, 2005
Chris Sauls wrote:
> Since 'export' is a protection attribute, you can end any 'export:' attribute-statement by introducing a new protection attribute, such as 'public'.  In other words:
> 
> # version(DLL_C) {
> #   export:
> #   extern(C):
> # }
> #
> # int forC_aaa() { ... }
> # int forC_bbb() { ... }
> #
> # public:
> # extern(D): // default is D, but it may be good to be explicit here
> #
> # int helper() { ... }
> #
> # version(DLL_D) {
> #   export:
> # }
> #
> # int aaa() { ... }
> # int bbb() { ... }
> #
> # public:


Thank you!


Michael