version and extern problems

Walter Bright newshound1 at digitalmars.com
Sat Jul 7 19:21:01 PDT 2007


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