www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Feature request: "noexport" keyword

reply Bekenn <leaveme alone.com> writes:
The "export" keyword is a protection attribute, along with "private", 
"package", "protected", and "public".  This means that it can be used 
with the same syntax as any of those other attributes; for instance, if 
creating a D "header" for an existing Windows DLL file, you might do 
something like this:

	export extern (Windows):
	void func1();
	int func2();
	...

This notation is convenient when dealing with a very large existing 
library; it avoids pointless repetition, and there's no need to keep 
track of a closing end brace (as there would be with the scoped version).

The problem here is that there is no way to cancel an export attribute. 
  Whereas the other protection attributes can be overridden either locally:

	public:
	void func1();
	package int func2();

...or globally:

	public:
	void func1();
	package:
	int func2();

...or with a scoped declaration, there is no way to specify that a given 
symbol should *not* be exported once the "export:" version is used, or 
inside a scoped export section.

A "noexport" keyword would be useful in these situations, if for 
instance you want to add very small convenience functions that are 
intended to be inlined and are not actually exported members of the DLL:

	export extern (Windows):
	void func1();
	int func2();
	const(char)* func3(int arg1, int arg2, const(char)* arg3, float arg4, 
int arg5, void* arg6);
	noexport const(char)* simpleFunc3(arg3, arg5, arg6) { return func3(0, 
0, arg3, 3.14, arg5, arg6);
	void func4();
	...

Currently, to get the same effect, you have to either declare 
simpleFunc3 above the export: line, use a scoped export block, or put 
simpleFunc3 in an entirely different file.  None of these provide the 
same level of convenience.

What do you guys think?
Feb 19 2011
next sibling parent reply "Nick Sabalausky" <a a.a> writes:
"Bekenn" <leaveme alone.com> wrote in message 
news:ijqffm$6lk$1 digitalmars.com...
 The "export" keyword is a protection attribute, along with "private", 
 "package", "protected", and "public".  This means that it can be used with 
 the same syntax as any of those other attributes; for instance, if 
 creating a D "header" for an existing Windows DLL file, you might do 
 something like this:

 export extern (Windows):
 void func1();
 int func2();
 ...

 This notation is convenient when dealing with a very large existing 
 library; it avoids pointless repetition, and there's no need to keep track 
 of a closing end brace (as there would be with the scoped version).

 The problem here is that there is no way to cancel an export attribute. 
 Whereas the other protection attributes can be overridden either locally:

 public:
 void func1();
 package int func2();

 ...or globally:

 public:
 void func1();
 package:
 int func2();

 ...or with a scoped declaration, there is no way to specify that a given 
 symbol should *not* be exported once the "export:" version is used, or 
 inside a scoped export section.

 A "noexport" keyword would be useful in these situations, if for instance 
 you want to add very small convenience functions that are intended to be 
 inlined and are not actually exported members of the DLL:

 export extern (Windows):
 void func1();
 int func2();
 const(char)* func3(int arg1, int arg2, const(char)* arg3, float arg4, int 
 arg5, void* arg6);
 noexport const(char)* simpleFunc3(arg3, arg5, arg6) { return func3(0, 0, 
 arg3, 3.14, arg5, arg6);
 void func4();
 ...

 Currently, to get the same effect, you have to either declare simpleFunc3 
 above the export: line, use a scoped export block, or put simpleFunc3 in 
 an entirely different file.  None of these provide the same level of 
 convenience.

 What do you guys think?

I'm not 100% certain, but I think this should already do what you want: export extern (Windows): void func1(); int func2(); public: void func3(); void func4();
Feb 19 2011
next sibling parent reply Bekenn <leaveme alone.com> writes:
On 2/19/2011 11:30 PM, Nick Sabalausky wrote:
 "Bekenn"<leaveme alone.com>  wrote in message
 news:ijqffm$6lk$1 digitalmars.com...
 I'm not 100% certain, but I think this should already do what you want:

 export extern (Windows):
 void func1();
 int func2();

 public:
 void func3();
 void func4();

Hmm... I think you may be right. I hadn't considered that, but it makes sense. I was thinking that the "export" attribute was independent of the other protection attributes, which would introduce an asymmetry: private, package, and public could each be overridden by supplying a different protection attribute, but export couldn't be overridden. However, thinking about it, a "private export" wouldn't make much sense (and "export" is listed as a protection attribute, right along with the others), so I guess they must all be mutually exclusive. I just tested this by trying to compile a module with the following line: public export void func(); The compiler rejects it with the message "redundant protection attribute." I think that pretty clearly settles this issue.
Feb 20 2011
parent reply "Nick Sabalausky" <a a.a> writes:
"Bekenn" <leaveme alone.com> wrote in message 
news:ijrjh2$20sv$1 digitalmars.com...
 On 2/19/2011 11:30 PM, Nick Sabalausky wrote:
 "Bekenn"<leaveme alone.com>  wrote in message
 news:ijqffm$6lk$1 digitalmars.com...
 I'm not 100% certain, but I think this should already do what you want:

 export extern (Windows):
 void func1();
 int func2();

 public:
 void func3();
 void func4();

Hmm... I think you may be right. I hadn't considered that, but it makes sense. I was thinking that the "export" attribute was independent of the other protection attributes, which would introduce an asymmetry: private, package, and public could each be overridden by supplying a different protection attribute, but export couldn't be overridden. However, thinking about it, a "private export" wouldn't make much sense (and "export" is listed as a protection attribute, right along with the others), so I guess they must all be mutually exclusive. I just tested this by trying to compile a module with the following line: public export void func(); The compiler rejects it with the message "redundant protection attribute." I think that pretty clearly settles this issue.

Yea. Actually I just happened to be reading the section about protection attributes in Andrei's "The D Programming Language" book just the other day, and the way it talked about them indicated they were all mutually-exclusive. Were it not for that, I probably would have made the same assumption as you. Not sure why, though, because as you say, "private/protected export" doesn't seem to make much sence.
Feb 20 2011
parent "Nick Sabalausky" <a a.a> writes:
"Nick Sabalausky" <a a.a> wrote in message 
news:ijs2f1$5ri$1 digitalmars.com...
 "Bekenn" <leaveme alone.com> wrote in message 
 news:ijrjh2$20sv$1 digitalmars.com...
 On 2/19/2011 11:30 PM, Nick Sabalausky wrote:
 "Bekenn"<leaveme alone.com>  wrote in message
 news:ijqffm$6lk$1 digitalmars.com...
 I'm not 100% certain, but I think this should already do what you want:

 export extern (Windows):
 void func1();
 int func2();

 public:
 void func3();
 void func4();

Hmm... I think you may be right. I hadn't considered that, but it makes sense. I was thinking that the "export" attribute was independent of the other protection attributes, which would introduce an asymmetry: private, package, and public could each be overridden by supplying a different protection attribute, but export couldn't be overridden. However, thinking about it, a "private export" wouldn't make much sense (and "export" is listed as a protection attribute, right along with the others), so I guess they must all be mutually exclusive. I just tested this by trying to compile a module with the following line: public export void func(); The compiler rejects it with the message "redundant protection attribute." I think that pretty clearly settles this issue.

Yea. Actually I just happened to be reading the section about protection attributes in Andrei's "The D Programming Language" book just the other day, and the way it talked about them indicated they were all mutually-exclusive. Were it not for that, I probably would have made the same assumption as you. Not sure why, though, because as you say, "private/protected export" doesn't seem to make much sence.

Keep in mind though, I have *no* idea how "extern(...)" fits in to all of this.
Feb 20 2011
prev sibling parent Bernard Helyer <b.helyer gmail.com> writes:
On Sun, 20 Feb 2011 16:50:25 -0500, Nick Sabalausky wrote:
 Keep in mind though, I have *no* idea how "extern(...)" fits in to all
 of this.

The linkage is separate to the access and will continue when you change from export to public.
Feb 20 2011
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Saturday 19 February 2011 23:19:39 Bekenn wrote:
 The "export" keyword is a protection attribute, along with "private",
 "package", "protected", and "public".  This means that it can be used
 with the same syntax as any of those other attributes; for instance, if
 creating a D "header" for an existing Windows DLL file, you might do
 something like this:
 
 	export extern (Windows):
 	void func1();
 	int func2();
 	...
 
 This notation is convenient when dealing with a very large existing
 library; it avoids pointless repetition, and there's no need to keep
 track of a closing end brace (as there would be with the scoped version).
 
 The problem here is that there is no way to cancel an export attribute.
   Whereas the other protection attributes can be overridden either locally:
 
 	public:
 	void func1();
 	package int func2();
 
 ...or globally:
 
 	public:
 	void func1();
 	package:
 	int func2();
 
 ...or with a scoped declaration, there is no way to specify that a given
 symbol should *not* be exported once the "export:" version is used, or
 inside a scoped export section.
 
 A "noexport" keyword would be useful in these situations, if for
 instance you want to add very small convenience functions that are
 intended to be inlined and are not actually exported members of the DLL:
 
 	export extern (Windows):
 	void func1();
 	int func2();
 	const(char)* func3(int arg1, int arg2, const(char)* arg3, float arg4,
 int arg5, void* arg6);
 	noexport const(char)* simpleFunc3(arg3, arg5, arg6) { return func3(0,
 0, arg3, 3.14, arg5, arg6);
 	void func4();
 	...
 
 Currently, to get the same effect, you have to either declare
 simpleFunc3 above the export: line, use a scoped export block, or put
 simpleFunc3 in an entirely different file.  None of these provide the
 same level of convenience.
 
 What do you guys think?

Just use braces with export. Problem solved. I can see why noexport could be useful, but there are plenty of other attributes which don't have a negative (e.g. nothrow and pure). If we want to add something like noexport, we probably want a more generic way to do it than adding no export. Of course, I _much_ prefer the way that Linux just exports all symbols, and you don't have have to specify which get exported and which don't (I _hate_ having to deal with that in Windows in C++ - _especially_ since I'm typically doing cross-platform stuff that then uses a macro, and I forget to use it, since it does nothing on Linux, and that's what I'm usually developing on). I hadn't even realized that D _had_ an export keyword. If anything, I'd argue that D should ditch it and just make _everything_ export and be done with it. - Jonathan M Davis
Feb 19 2011
prev sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Sun, 20 Feb 2011 02:19:39 -0500, Bekenn <leaveme alone.com> wrote:

 The "export" keyword is a protection attribute, along with "private",  
 "package", "protected", and "public".  This means that it can be used  
 with the same syntax as any of those other attributes; for instance, if  
 creating a D "header" for an existing Windows DLL file, you might do  
 something like this:

 	export extern (Windows):
 	void func1();
 	int func2();
 	...

 This notation is convenient when dealing with a very large existing  
 library; it avoids pointless repetition, and there's no need to keep  
 track of a closing end brace (as there would be with the scoped version).

 The problem here is that there is no way to cancel an export attribute.  
   Whereas the other protection attributes can be overridden either  
 locally:

 	public:
 	void func1();
 	package int func2();

 ...or globally:

 	public:
 	void func1();
 	package:
 	int func2();

 ...or with a scoped declaration, there is no way to specify that a given  
 symbol should *not* be exported once the "export:" version is used, or  
 inside a scoped export section.

 A "noexport" keyword would be useful in these situations, if for  
 instance you want to add very small convenience functions that are  
 intended to be inlined and are not actually exported members of the DLL:

 	export extern (Windows):
 	void func1();
 	int func2();
 	const(char)* func3(int arg1, int arg2, const(char)* arg3, float arg4,  
 int arg5, void* arg6);
 	noexport const(char)* simpleFunc3(arg3, arg5, arg6) { return func3(0,  
 0, arg3, 3.14, arg5, arg6);
 	void func4();
 	...

 Currently, to get the same effect, you have to either declare  
 simpleFunc3 above the export: line, use a scoped export block, or put  
 simpleFunc3 in an entirely different file.  None of these provide the  
 same level of convenience.

 What do you guys think?

I think static should override export. But in any case, attributes are universally applicable in multiple ways (including using scope braces). This would probably solve your problem: extern (Windows): export { void func1(); void func2(); const(char)* func3(int arg1, int arg2, const(char)* arg3, float arg4, int arg5, void* arg6); void func4(); ... } const(char)* simpleFunc3(arg3, arg5, arg6) { return func3(0, 0, arg3, 3.14, arg5, arg6);
Feb 20 2011