View mode: basic / threaded / horizontal-split · Log in · Help
July 08, 2007
Re: version and extern problems
This sounds like the perfect place for alias, or something like it.  The 
idea would be to write code like this:

--------------
version(Windows)
  <do alias declaration here>;
else
  <do other alias delcaration here>;

extern(myAlias) typedef void function() foo;
--------------

Problem is, I haven't yet found a syntax that I like.  I came up with 3 
possibilities:

1) alias extern(Windows) extern(myAlias);

I don't like the extern(mine) part, because it reminds me too much of C 
function pointers.  That was a good example of a nice theoretical syntax 
that never worked in practice, IMHO.

Plus, this syntax could easily be read as "extern(Windows) attribute on 
the type extern(mine)..."  Technically, I guess the grammar's not 
ambiguous, but it's ugly.

2) alias extern(Windows) myAlias;

I don't like how this breaks the parallelism.  Would you use the alias 
extern(myAlias)?  Or would you drop the extern() part around it?  If the 
latter, how would you parse it without ambiguities?

Plus, the same problem as before where it looks like extern(Windows) is 
an attribute on something else.

3) alias Windows myAlias;

I presume that Windows isn't a valid symbol, so this has its own problems.


Thoughts?  About the concept in general, or about a good syntax?

Russ

Walter Bright wrote:
> Bug 1311 http://d.puremagic.com/issues/show_bug.cgi?id=1311
> is about using version declarations to control part of a following 
> declaration (or series of declarations):
> 
> -------------------------
> version(Windows)
>     extern(Windows):
> else
>     extern(C):
> 
> typedef void function() foo;
> --------------------------
> 
> This does not work now, and it was a bug that it ever did appear to 
> work. The issue is that version declarations can only affect entire 
> declarations, not parts of them. An extern statement with a : is 
> implicitly the same as:
> 
> ----------------
> extern(Windows):
> int a;
> int b;
> -----is same as---
> extern(Windows)
> {
>    int a;
>    int b;
> }
> -----------------
> 
> That cannot be split up with a version declaration; it would be like 
> trying to make:
> 
>     version (Windows)
>         int
>     else
>         long
>     x;
> 
> work. The old behavior of dmd contained a serious (unreported) bug where 
> such constructs would cause forward references to behave unpredictably.
> 
> So, the question is how to get the same effect? The alternatives are:
> 
> 1.
> version(Windows)
> {
>     extern(Windows):
>        typedef void function() foo;
> }
> else
> {
>     extern(C):
>        typedef void function() foo;
> }
> 
> Yes, that means doing a cut & paste on the code in the braces. Not 
> thrilling, but it works.
> 
> 2. Stop using extern(Windows). The Windows calling convention is only 
> necessary when a) calling Win32 API functions (which don't exist on 
> Linux anyway) and b) calling someone else's C code that pointlessly and 
> spuriously uses the Windows calling convention, and cannot be fixed.
> There is no reason in new C/C++ code to ever use the Windows calling 
> convention.
> 
> 3. Create two source files, one for the extern(Windows) and the other 
> for the extern(C). Have your makefile automatically copy one to the 
> other, using sed to edit that one line. Import one under Windows, the 
> other under Linux.
> 
> 4. Wait for the future 2.0 macro feature, which should be able to deal 
> with this nicely:
> 
> macro Foo()
> {
>     typedef void function() foo;
> }
> version(Windows)
> {   extern(Windows): Foo(); }
> else
> {    extern(C): Foo(); }
> 
> 5. Do the same as (4) using string mixins:
> 
> const string Foo =
> "
>     typedef void function() foo;
> ";
> version(Windows)
> {   extern(Windows): mixin(Foo); }
> else
> {    extern(C): mixin(Foo); }
> 
> 
> 6. Use template mixins:
> 
> template Foo()
> {
>     typedef void function() foo;
> }
> version(Windows)
> {   extern(Windows): mixin Foo; }
> else
> {    extern(C): mixin Foo; }
July 08, 2007
Re: version and extern problems
Russell Lewis wrote:
> This sounds like the perfect place for alias, or something like it.  The 
> idea would be to write code like this:
> 

(...)

> 
> 2) alias extern(Windows) myAlias;
> 
> I don't like how this breaks the parallelism.  Would you use the alias 
> extern(myAlias)?  Or would you drop the extern() part around it?  If the 
> latter, how would you parse it without ambiguities?
> 
> Plus, the same problem as before where it looks like extern(Windows) is 
> an attribute on something else.

This is exactly what I thought while reading the OP. Maybe it would be 
clearer if the scope syntax is reused for alias:

version (Windows)
	alias(extern) Windows MyAlias;
else
	alias(extern) C MyAlias;

extern(MyAlias):

void foo();
void bar();

...
July 08, 2007
Re: version and extern problems
Reply to Russell,

> This sounds like the perfect place for alias, or something like it.
> The idea would be to write code like this:
> 
> --------------
> version(Windows)
> <do alias declaration here>;
> else
> <do other alias delcaration here>;
> extern(myAlias) typedef void function() foo;
> --------------
> Problem is, I haven't yet found a syntax that I like.  I came up with
> 3 possibilities:
> 
> 1) alias extern(Windows) extern(myAlias);
> 

how about alow extern to take a string?

const char[] type = "Windows";

extern(type);
July 09, 2007
Re: version and extern problems
Walter Bright wrote:
> Bug 1311 http://d.puremagic.com/issues/show_bug.cgi?id=1311
> is about using version declarations to control part of a following 
> declaration (or series of declarations):
> 
> -------------------------
> version(Windows)
>     extern(Windows):
> else
>     extern(C):
> 
> typedef void function() foo;
> --------------------------
> 
> This does not work now, and it was a bug that it ever did appear to 
> work. The issue is that version declarations can only affect entire 
> declarations, not parts of them. An extern statement with a : is 
> implicitly the same as:
> 
> ----------------
> extern(Windows):
> int a;
> int b;
> -----is same as---
> extern(Windows)
> {
>    int a;
>    int b;
> }
> -----------------
> 
> That cannot be split up with a version declaration; it would be like 
> trying to make:
> 
>     version (Windows)
>         int
>     else
>         long
>     x;
> 
> work. The old behavior of dmd contained a serious (unreported) bug where 
> such constructs would cause forward references to behave unpredictably.
> 
> So, the question is how to get the same effect? The alternatives are:
> 
> 1.
> version(Windows)
> {
>     extern(Windows):
>        typedef void function() foo;
> }
> else
> {
>     extern(C):
>        typedef void function() foo;
> }
> 
> Yes, that means doing a cut & paste on the code in the braces. Not 
> thrilling, but it works.
> 
> 2. Stop using extern(Windows). The Windows calling convention is only 
> necessary when a) calling Win32 API functions (which don't exist on 
> Linux anyway) and b) calling someone else's C code that pointlessly and 
> spuriously uses the Windows calling convention, and cannot be fixed.
> There is no reason in new C/C++ code to ever use the Windows calling 
> convention.

Unfortunately (b) is extremely common, including on some significant libraries.
(eg, MySQL).
We really need a solution to this.
July 09, 2007
Re: version and extern problems
Walter Bright wrote:
> Bug 1311 http://d.puremagic.com/issues/show_bug.cgi?id=1311
> is about using version declarations to control part of a following 
> declaration (or series of declarations):
> 
> -------------------------
> version(Windows)
>     extern(Windows):
> else
>     extern(C):
> 
> typedef void function() foo;
> --------------------------
> 
> This does not work now, and it was a bug that it ever did appear to 
> work. The issue is that version declarations can only affect entire 
> declarations, not parts of them. An extern statement with a : is 
> implicitly the same as:
> 
> ----------------
> extern(Windows):
> int a;
> int b;
> -----is same as---
> extern(Windows)
> {
>    int a;
>    int b;
> }
> -----------------
> 
> That cannot be split up with a version declaration;


Why not

  extern(ecc) void function() foo;

where ecc would resolve to Windows or C.

This of course requires some tweaking of the compiler, but it might be 
worth it.
July 09, 2007
Re: version and extern problems
Walter Bright wrote:
> Mike Wey wrote:
>> Should this work?
>>
>> version(Windows)
>> {   const char[] external = "extern(Windows):"; }
>> else
>> {   const char[] external = "extern(C):"; }
>>
>> mixin(external);
>> typedef void function() foo;
> 
> No, it doesn't work (although it compiles).

That seems like it should work.  Is the problem something to do with the 
order in which things are evaluated at compile-time?


Sean
July 09, 2007
Re: version and extern problems
I guess that:

mixin("extern(C):");
typedef void function() foo;

is the same as:

extern(C){}
typedef void function() foo;

Sean Kelly wrote:
> Walter Bright wrote:
>> Mike Wey wrote:
>>> Should this work?
>>>
>>> version(Windows)
>>> {   const char[] external = "extern(Windows):"; }
>>> else
>>> {   const char[] external = "extern(C):"; }
>>>
>>> mixin(external);
>>> typedef void function() foo;
>>
>> No, it doesn't work (although it compiles).
> 
> That seems like it should work.  Is the problem something to do with the 
> order in which things are evaluated at compile-time?
> 
> 
> Sean
July 09, 2007
Re: version and extern problems
Sean Kelly wrote:
> That seems like it should work.  Is the problem something to do with the 
> order in which things are evaluated at compile-time?

It doesn't work because mixin is supposed to be a complete statement, 
not part of one. The XXX: forms a prefix, not a complete statement.
July 09, 2007
Re: version and extern problems
Don Clugston wrote:
> Unfortunately (b) is extremely common, including on some significant 
> libraries.
> (eg, MySQL).

I know. I was just hoping to head off *new* code being written that way.

> We really need a solution to this.

I proposed several, they should work.
July 09, 2007
Re: version and extern problems
Georg Wrede wrote:
> Why not
> 
>   extern(ecc) void function() foo;
> 
> where ecc would resolve to Windows or C.
> 
> This of course requires some tweaking of the compiler, but it might be 
> worth it.

Do you mean "ecc" being a magic identifier that the compiler sets to 
Windows on Windows, and C otherwise? That might be a pretty good idea. 
Why "ecc", though? It doesn't jump out at me what it might mean.

How about "System" ?
1 2 3 4 5 6
Top | Discussion index | About this forum | D home