version and extern problems

Mike Wey no.spam at example.com
Sun Jul 8 07:16:18 PDT 2007


Should this work?

version(Windows)
{   const char[] external = "extern(Windows):"; }
else
{   const char[] external = "extern(C):"; }

mixin(external);
typedef void function() foo;

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; }



More information about the Digitalmars-d mailing list