digitalmars.D - version and extern problems
- Walter Bright (86/86) Jul 07 2007 Bug 1311 http://d.puremagic.com/issues/show_bug.cgi?id=1311
- Mike Parker (35/140) Jul 07 2007 Then I misunderstood the usage of version. I was under the impression
- Jarrett Billingsley (5/10) Jul 08 2007 No. It's a form of conditional compilation, certainly, but it's not jus...
- Jason House (10/50) Jul 08 2007 This seems like a real loss for the convenience of D. One of the assets...
- Jarrett Billingsley (5/8) Jul 08 2007 I agree. I think it's funny that none of the proposed solutions are
- Mike Wey (8/113) Jul 08 2007 Should this work?
- torhu (6/16) Jul 08 2007 DMD 1.018 accepts that. But maybe that's a bug too, since string mixins...
- torhu (8/25) Jul 08 2007 That the mixing trick works might be as bad as that this works:
- Walter Bright (2/11) Jul 08 2007 No, it doesn't work (although it compiles).
- Sean Kelly (4/16) Jul 09 2007 That seems like it should work. Is the problem something to do with the...
- Mike Wey (7/26) Jul 09 2007 I guess that:
- Walter Bright (3/5) Jul 09 2007 It doesn't work because mixin is supposed to be a complete statement,
- Sean Kelly (3/9) Jul 09 2007 Ah, I didn't know that. Thanks.
- Jason House (3/9) Jul 09 2007 I thought "gotolabel:" would be a prefix but "private:" isn't. Is there...
- torhu (27/90) Jul 08 2007 I don't like any of these solutions. This is so straight forward with
- Russell Lewis (29/134) Jul 08 2007 This sounds like the perfect place for alias, or something like it. The...
- =?ISO-8859-1?Q?Julio_C=E9sar_Carrascal_Urquijo?= (12/24) Jul 08 2007 This is exactly what I thought while reading the OP. Maybe it would be
- BCS (4/19) Jul 08 2007 how about alow extern to take a string?
- Don Clugston (4/69) Jul 09 2007 Unfortunately (b) is extremely common, including on some significant lib...
- Walter Bright (3/7) Jul 09 2007 I proposed several, they should work.
- Georg Wrede (6/37) Jul 09 2007 Why not
- Walter Bright (5/13) Jul 09 2007 Do you mean "ecc" being a magic identifier that the compiler sets to
- Carlos Santander (7/22) Jul 09 2007 I'm guessing this would be the default calling convention for the system...
- Walter Bright (5/10) Jul 09 2007 No, it would be what is necessary to interface to packages that pick
- Carlos Santander (4/15) Jul 09 2007 Ok, thanks.
- Russell Lewis (11/22) Jul 10 2007 By this argument, it could just as easily be called "Broken". I am
- Extrawurst (3/16) Jul 09 2007 i like this idea !
- Mike Parker (2/17) Jul 10 2007 Please :) This looks like a great solution. And extern(System) is intuit...
- torhu (10/28) Jul 10 2007 Yes, but what the Pascal convention? And the windows API uses more then...
- Walter Bright (4/5) Jul 10 2007 People who #ifdef their C code to use Pascal on one platform and C on
- Don Clugston (2/17) Jul 10 2007 IMHO, extern(System) would be fantastic.
- Walter Bright (2/3) Jul 10 2007 It's a kludge, but a very useful one. I'll fold it into the next update.
- Chris Miller (10/20) Jul 10 2007 be =
- Walter Bright (2/10) Jul 10 2007 It's the old chicken-and-egg problem of forward references.
- Jarrett Billingsley (3/4) Jul 10 2007 Mind elaborating? I can't see how this is a forward reference issue.
- BCS (4/11) Jul 10 2007 extern(A) const char[] A = "foo";
- Chris Miller (5/16) Jul 10 2007 I think problems like that exist all over the place; just don't do it.
- Walter Bright (2/7) Jul 10 2007 Sure. What if the string is a const string defined after it is used?
- BCS (11/22) Jul 10 2007 That is one thing I have never understood: why does lexical order ever (...
- Walter Bright (3/5) Jul 10 2007 const string x = "abc" ~ foo;
- nonnymouse (2/8) Jul 10 2007 Surely that's just an "x is not defined on line 2" error?
- 0ffh (13/14) Jul 11 2007 Nope. This, for example, is a perfectly valid D programme:
- Bill Baxter (10/30) Jul 11 2007 The snippet you snipped was:
- 0ffh (6/12) Jul 11 2007 I get that, really, I do.
- nonnymouse (8/9) Jul 11 2007 [snip]
- 0ffh (8/20) Jul 11 2007 Oops, now I get your drift. I was indeed misunderstanding you!
- Chris Miller (8/13) Jul 10 2007 r =
- BCS (15/22) Jul 10 2007 That has little or nothing to do with lexical order. Baring retro-order ...
- Jarrett Billingsley (4/8) Jul 10 2007 Then fail. It still wouldn't prevent the much more sensible and commond...
- Walter Bright (4/12) Jul 10 2007 There are several bug reports marked as important in bugzilla where
- Georg Wrede (10/25) Jul 11 2007 I wanted the discussion to stay with the (dis)merits of the idea itself,...
- Derek Parnell (13/16) Jul 11 2007 Especially when there are so many great keywords that we can further
- Derek Parnell (8/23) Jul 11 2007 Damn ... I forgot a couple ...
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; }
Jul 07 2007
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; } -----------------Right. But since version doesn't create a new scope, what's the problem?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.Then I misunderstood the usage of version. I was under the impression that it's a form of conditional compilation, i.e. on Windows the final result would be int x; Is that not possible?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.I implemented it as I did to avoid this. Using multiple declarations is error prone and a maintenance nightmare, particularly for the number of declarations I'm dealing with.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, I have no choice. This is not new D code, but bindings to existing cross-platform C libraries (namely OpenGL and DevIL). On Windows, these libraries all use the stdcall calling convention. Declaring them as extern(C) causes crashes. On other platforms, the libraries use the C calling convention, so they can't be declared extern(Windows) there. Every D OpenGL binding I have seen uses this technique. That's how I first learned it. For example, all of Kenta Cho's D games (http://www.asahi-net.or.jp/~cs8k-cyu/index_e.html) use an OpenGL module with this at the top: version (Win32) { private import std.c.windows.windows; extern(Windows): } else { extern(C): } followed by the function declarations. Most of his code already won't compile on newer versions without modification anyway. But still, now all of the D OpenGL bindings are broken.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.Yuck! :)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(); }That will be nice when it gets here, but there are already a lot of people using this library who aren't going to be willing to wait.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; }It looks like one of these is going to be the best alternative. More typing, but at least it keeps the declarations in one place.
Jul 07 2007
"Mike Parker" <aldacron71 yahoo.com> wrote in message news:f6pr67$2t00$1 digitalmars.com...Then I misunderstood the usage of version. I was under the impression that it's a form of conditional compilation, i.e. on Windows the final result would be int x; Is that not possible?No. It's a form of conditional compilation, certainly, but it's not just like #ifdef. Everything within a version block must be syntactically valid; "int" is not syntactically valid, so you can't put it in the version block.
Jul 08 2007
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; } -----------------This seems like a real loss for the convenience of D. One of the assets of the D language is that it makes a lot of things simple. The example in the bug is fairly intuitive and easy to write.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.This restriction seems reasonable. It'd be really, really tough to handle. In my mind, the issue is that the : operator might make sense if the attribute: only applied to it's contained scope. In this case, however, that doesn't really make sense, because version statements don't really have their own scope... Otherwise, variable definitions inside of them wouldn't be available externally.
Jul 08 2007
"Jason House" <jason.james.house gmail.com> wrote in message news:f6qq5d$1s0u$1 digitalmars.com...This seems like a real loss for the convenience of D. One of the assets of the D language is that it makes a lot of things simple. The example in the bug is fairly intuitive and easy to write.I agree. I think it's funny that none of the proposed solutions are anywhere near as simple or intuitive as the old, incorrect syntax. Perhaps this is telling.
Jul 08 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; }
Jul 08 2007
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;DMD 1.018 accepts that. But maybe that's a bug too, since string mixins are supposed to be either an expression, a statement, or a declaration or definition? According to the spec, it seems to be a valid AttributeSpecifier, which in turn is a valid DeclDef. But Walter didn't suggest it as a workaround, which makes me worried.
Jul 08 2007
torhu wrote:Mike Wey wrote:That the mixing trick works might be as bad as that this works: --- version (Windows) extern (Windows): --- Being able to insert 'extern (Windows):' using a string mixin seems equally bad to me. Where's the important difference?Should this work? version(Windows) { const char[] external = "extern(Windows):"; } else { const char[] external = "extern(C):"; } mixin(external); typedef void function() foo;DMD 1.018 accepts that. But maybe that's a bug too, since string mixins are supposed to be either an expression, a statement, or a declaration or definition? According to the spec, it seems to be a valid AttributeSpecifier, which in turn is a valid DeclDef. But Walter didn't suggest it as a workaround, which makes me worried.
Jul 08 2007
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).
Jul 08 2007
Walter Bright wrote:Mike Wey wrote:That seems like it should work. Is the problem something to do with the order in which things are evaluated at compile-time? SeanShould 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).
Jul 09 2007
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:That seems like it should work. Is the problem something to do with the order in which things are evaluated at compile-time? SeanShould 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).
Jul 09 2007
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.
Jul 09 2007
Walter Bright wrote:Sean Kelly wrote:Ah, I didn't know that. Thanks. SEanThat 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.
Jul 09 2007
Walter Bright wrote:Sean Kelly wrote:I thought "gotolabel:" would be a prefix but "private:" isn't. Is there a big reason that distinction isn't true?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.
Jul 09 2007
Walter Bright wrote:I don't like any of these solutions. This is so straight forward with the C preprocessor. Even using the future macro feature means duplicating definitions. AFAIK, these problems only affect the linkage attributes, meaning extern (C), extern (Windows), and export. If Mike Wey's string mixin solution is allowed in future dmd versions, I guess the situation isn't that bad. As long as bug 1306 is fixed, anyway. Another way would be to accept that this is a special case that needs a pragmatic solution, and expand the syntax a bit: extern (Windows, C): According to the docs, A D compiler only need to support Windows and Pascal conventions on Windows. So on other platforms, the compiler could just pick the first valid linkage for that platform. A version ID could be incorporated too, if there's ever a need for it: extern (Windows : Windows; WeirdPlatform: WeirdLinkage; C): The problem with 'export' is related. I wonder if something similar could work for that. Make it conditional somehow: export (DLLVERSION) int someVar; export (version DLLVERSION) int someVar; version (DLLVERSION)(export) int someVar; The third version has the advantage of being applicable to other cases too: version (Windows) (extern (Windows)) else (extern (C)) { /* openGL prototypes */ } I don't know if this syntax is feasible, I'll leave that to the experts. :)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; }
Jul 08 2007
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; }
Jul 08 2007
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(); ...
Jul 08 2007
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);
Jul 08 2007
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.
Jul 09 2007
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.
Jul 09 2007
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.
Jul 09 2007
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" ?
Jul 09 2007
Walter Bright escribió:Georg Wrede wrote:I'm guessing this would be the default calling convention for the system. If the system was written in C++ (BeOS?), would it have to mean "extern(C++)"? If someone wrote an OS in D, would it just be "extern(D)"? Or would it just be specified that "System" means "Windows" on Windows and "C" everywhere else? -- Carlos Santander BernalWhy 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" ?
Jul 09 2007
Carlos Santander wrote:I'm guessing this would be the default calling convention for the system. If the system was written in C++ (BeOS?), would it have to mean "extern(C++)"? If someone wrote an OS in D, would it just be "extern(D)"? Or would it just be specified that "System" means "Windows" on Windows and "C" everywhere else?No, it would be what is necessary to interface to packages that pick pointless things like "Windows" calling conventions. If lots of C packages used "FooBar" calling conventions on XXX, then it would mean "FooBar" on that system.
Jul 09 2007
Walter Bright escribió:Carlos Santander wrote:Ok, thanks. -- Carlos Santander BernalI'm guessing this would be the default calling convention for the system. If the system was written in C++ (BeOS?), would it have to mean "extern(C++)"? If someone wrote an OS in D, would it just be "extern(D)"? Or would it just be specified that "System" means "Windows" on Windows and "C" everywhere else?No, it would be what is necessary to interface to packages that pick pointless things like "Windows" calling conventions. If lots of C packages used "FooBar" calling conventions on XXX, then it would mean "FooBar" on that system.
Jul 09 2007
Walter Bright wrote:Carlos Santander wrote:By this argument, it could just as easily be called "Broken". I am concerned that calling it "System" will encourage widespread use...which is a step in exactly what you said was the wrong direction. Did you see the post about using strings for extern? That seemed like an elegant solution to me: version(Windows) const char[] myExternAlias = "Windows"; else const char[] myExternAlias = "C"; extern(myExternAlias) void foo();I'm guessing this would be the default calling convention for the system. If the system was written in C++ (BeOS?), would it have to mean "extern(C++)"? If someone wrote an OS in D, would it just be "extern(D)"? Or would it just be specified that "System" means "Windows" on Windows and "C" everywhere else?No, it would be what is necessary to interface to packages that pick pointless things like "Windows" calling conventions. If lots of C packages used "FooBar" calling conventions on XXX, then it would mean "FooBar" on that system.
Jul 10 2007
i like this idea ! /signed Walter Bright schrieb: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" ?
Jul 09 2007
Walter Bright wrote:Georg Wrede wrote:Please :) This looks like a great solution. And extern(System) is intuitive.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" ?
Jul 10 2007
Mike Parker wrote:Walter Bright wrote:Yes, but what the Pascal convention? And the windows API uses more then those three conventions, too. This system isn't very flexible in case other platforms start using more than one convention. Maybe Windows and Pascal could just 'degrade' into C on other platforms than windows? Or allowing several possibilities: extern (Windows, C) Windows is picked on Windows, C on other platforms. This allows you to control what happens.Georg Wrede wrote:Please :) This looks like a great solution. And extern(System) is intuitive.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" ?
Jul 10 2007
torhu wrote:Yes, but what the Pascal convention?People who #ifdef their C code to use Pascal on one platform and C on another should be excommunicated, and their software should be stricken from all monuments.
Jul 10 2007
Walter Bright wrote:Georg Wrede wrote:IMHO, extern(System) would be fantastic.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" ?
Jul 10 2007
Don Clugston wrote:IMHO, extern(System) would be fantastic.It's a kludge, but a very useful one. I'll fold it into the next update.
Jul 10 2007
On Mon, 09 Jul 2007 14:01:11 -0400, Walter Bright = <newshound1 digitalmars.com> wrote:Georg Wrede wrote:be =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 =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" ?I don't know; why not let it just be a string literal... version(Windows) const char[] mylibcall =3D "Windows"; else const char[] mylibcall =3D "C"; extern(mylibcall) void function() foo;
Jul 10 2007
Chris Miller wrote:I don't know; why not let it just be a string literal... version(Windows) const char[] mylibcall = "Windows"; else const char[] mylibcall = "C"; extern(mylibcall) void function() foo;It's the old chicken-and-egg problem of forward references.
Jul 10 2007
"Walter Bright" <newshound1 digitalmars.com> wrote in message news:f70mvo$22e7$1 digitalmars.com...It's the old chicken-and-egg problem of forward references.Mind elaborating? I can't see how this is a forward reference issue.
Jul 10 2007
Reply to Jarrett,"Walter Bright" <newshound1 digitalmars.com> wrote in message news:f70mvo$22e7$1 digitalmars.com...extern(A) const char[] A = "foo"; but as long as you don't worry about symbol names untill you are making .o files that isn't a problem (I would think).It's the old chicken-and-egg problem of forward references.Mind elaborating? I can't see how this is a forward reference issue.
Jul 10 2007
On Tue, 10 Jul 2007 16:55:47 -0400, BCS <ao pathlink.com> wrote:Reply to Jarrett,"Walter Bright" <newshound1 digitalmars.com> wrote in message news:f70mvo$22e7$1 digitalmars.com...It's the old chicken-and-egg problem of forward references.Mind elaborating? I can't see how this is a forward reference issue.=g =extern(A) const char[] A =3D "foo"; but as long as you don't worry about symbol names untill you are makin=.o files that isn't a problem (I would think).I think problems like that exist all over the place; just don't do it. int foo =3D foo.init; I would like to know what Walter is referring to too.
Jul 10 2007
Jarrett Billingsley wrote:"Walter Bright" <newshound1 digitalmars.com> wrote in message news:f70mvo$22e7$1 digitalmars.com...Sure. What if the string is a const string defined after it is used?It's the old chicken-and-egg problem of forward references.Mind elaborating? I can't see how this is a forward reference issue.
Jul 10 2007
Reply to Walter,Jarrett Billingsley wrote:That is one thing I have never understood: why does lexical order ever (outside of statement lists e.i. function) ever cause an issue? I would expect that all of these issues could be removed by having one pass over the AST find the symbols (without getting types or anything else). Then another pass starts filling them out by reclusively evaluating symbols. The only issue I see right off involve non-determinism of some things like static asserts and ifs and how errors are found. But I think that that could be removed (or rendered irrelevant) for cases where errors aren't present. Then again, my experience with compilers stops just barely after lexers. However I /am/ genuinely interested in your thoughts on this."Walter Bright" <newshound1 digitalmars.com> wrote in message news:f70mvo$22e7$1 digitalmars.com...Sure. What if the string is a const string defined after it is used?It's the old chicken-and-egg problem of forward references.Mind elaborating? I can't see how this is a forward reference issue.
Jul 10 2007
BCS wrote:That is one thing I have never understood: why does lexical order ever (outside of statement lists e.i. function) ever cause an issue?const string x = "abc" ~ foo; const string foo = x[1..4];
Jul 10 2007
Walter Bright Wrote:BCS wrote:Surely that's just an "x is not defined on line 2" error?That is one thing I have never understood: why does lexical order ever (outside of statement lists e.i. function) ever cause an issue?const string x = "abc" ~ foo; const string foo = x[1..4];
Jul 10 2007
nonnymouse wrote:Surely that's just an "x is not defined on line 2" error?Nope. This, for example, is a perfectly valid D programme: ---<snip>--- module test; int y=3+x; const int x=5; void main() { printf("x=%i y=%i\n",x,y); } ---<snap>--- Seems like D collects all declarations first, unlike C. Regards, Frank
Jul 11 2007
0ffh wrote:nonnymouse wrote:The snippet you snipped was: const string x = "abc" ~ foo; const string foo = x[1..4]; So more like const int y=3+x; const int x=5+y; No matter which order you scan that, you can't come to a valid order of initialization. --bbSurely that's just an "x is not defined on line 2" error?Nope. This, for example, is a perfectly valid D programme: ---<snip>--- module test; int y=3+x; const int x=5; void main() { printf("x=%i y=%i\n",x,y); } ---<snap>--- Seems like D collects all declarations first, unlike C. Regards, Frank
Jul 11 2007
Bill Baxter wrote:So more like const int y=3+x; const int x=5+y; No matter which order you scan that, you can't come to a valid order of initialization.I get that, really, I do. I just wanted to point out why 'Surely that's just an "x is not defined on line 2" error?' does not hold, nor is to the point (which you just repeated). Regards, frank
Jul 11 2007
0ffh Wrote:Nope. This, for example, is a perfectly valid D program:[snip] Then it must be "foo is not defined on line 1". ;-) I think maybe you thought I said line 1 last time. I said line 2. I was assuming that the compiler had looked ahead and come to a dead-end (or more expressively: a cul-de-sac). (We are assuming that is either the whole program or the only lines that matter here are we?) At some point, even if it is just before code generation all these symbols need to be defined. The compiler must choose a, possibly arbitrary, order in which it fills them. Surely when going through the AST to do this for a particular symbol, if it meets itself further down the tree it throws an error. I chose a sarcastically vague one.. "Symbol x cannot de defined as definition of x is based on definition of x" might make a bit more sense. Please, if possible, read this as a question rather than an answer. i.e I would genuinely like to be corrected where I have misunderstood (or missed out) some of the complexities of these issues.
Jul 11 2007
nonnymouse wrote:0ffh Wrote:Oops, now I get your drift. I was indeed misunderstanding you! I think one might rather choose to call it a circular or recursive problem...Nope. This, for example, is a perfectly valid D program:[snip] Then it must be "foo is not defined on line 1". ;-) I think maybe you thought I said line 1 last time. I said line 2. I was assuming that the compiler had looked ahead and come to a dead-end (or more expressively: a cul-de-sac). (We are assuming that is either the whole program or the only lines that matter here are we?)At some point, even if it is just before code generation all these symbols need to be defined. [...] "Symbol x cannot de defined as definition of x is based on definition of x" might make a bit more sense. Please, if possible, read this as a question rather than an answer. i.e I would genuinely like to be corrected where I have misunderstood (or missed out) some of the complexities of these issues.Well, I think the gist of your explanation is right, even if we cannot know about the actual implementation details. Regards, frank p.s. Funny thing, I don't get you; and in turn Bill doesn't get me! That's Karma, if not coincidence! ;-)
Jul 11 2007
On Tue, 10 Jul 2007 20:24:23 -0400, Walter Bright = <newshound1 digitalmars.com> wrote:BCS wrote:r =That is one thing I have never understood: why does lexical order eve=This is always an issue and should cause an error, if extern uses string= s = or not. How does this really pertain to extern that doesn't cause proble= ms = even without the requested feature?(outside of statement lists e.i. function) ever cause an issue?const string x =3D "abc" ~ foo; const string foo =3D x[1..4];
Jul 10 2007
Reply to Walter,BCS wrote:That has little or nothing to do with lexical order. Baring retro-order dependencies does remove this type of error, but it also bars otherwise valid code. I would propose that the evaluation could run like this: use rand() to pick something to start with (not needed but it would work anyway) attempt to evaluate value of foo foo requires x attempt to evaluate value of x x requires foo we have started but not finished evaluating x therefor "Error: cyclical dependency for foo" The same model could be used for auto typing, template evaluation or whatever. As long as you never have to evaluate something as part of evaluating itself, order can be ignored.That is one thing I have never understood: why does lexical order ever (outside of statement lists e.i. function) ever cause an issue?const string x = "abc" ~ foo; const string foo = x[1..4];
Jul 10 2007
"Walter Bright" <newshound1 digitalmars.com> wrote in message news:f70vtc$opn$1 digitalmars.com...Jarrett Billingsley wrote:Then fail. It still wouldn't prevent the much more sensible and commond case of defining the string _before_ the extern.Mind elaborating? I can't see how this is a forward reference issue.Sure. What if the string is a const string defined after it is used?
Jul 10 2007
Jarrett Billingsley wrote:"Walter Bright" <newshound1 digitalmars.com> wrote in message news:f70vtc$opn$1 digitalmars.com...There are several bug reports marked as important in bugzilla where people are very desirous of using things lexically before they are defined. I do not wish to add to it.Jarrett Billingsley wrote:Then fail. It still wouldn't prevent the much more sensible and commond case of defining the string _before_ the extern.Mind elaborating? I can't see how this is a forward reference issue.Sure. What if the string is a const string defined after it is used?
Jul 10 2007
Walter Bright wrote:Georg Wrede wrote:I wanted the discussion to stay with the (dis)merits of the idea itself, and not (as usual) begin with bickering about the choice of word. For a similar reason I avoided taking a stance on whether ecc should be automatic, user settable or user overridable. (Pascal comes to mind, but you murdered that in a follow-up post. ;-) ) BTW, what are the implications of an automatic-only ecc for cross compiling with gdc? (I thought it was obvious: ecc for External Calling Convention. :-) )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" ?I'm not entirely opposed to System. Still, System is a big word.
Jul 11 2007
On Wed, 11 Jul 2007 15:27:44 +0300, Georg Wrede wrote:Especially when there are so many great keywords that we can further overload <G> extern(auto) extern(default) extern(static) extern(type) extern(override) . . . -- Derek Parnell Melbourne, Australia "Down with mediocrity!"How about "System" ?I'm not entirely opposed to System. Still, System is a big word.
Jul 11 2007
On Wed, 11 Jul 2007 22:47:32 +1000, Derek Parnell wrote:On Wed, 11 Jul 2007 15:27:44 +0300, Georg Wrede wrote:Damn ... I forgot a couple ... extern(extern) extern() -- Derek Parnell Melbourne, Australia "Down with mediocrity!"Especially when there are so many great keywords that we can further overload <G> extern(auto) extern(default) extern(static) extern(type) extern(override) . . .How about "System" ?I'm not entirely opposed to System. Still, System is a big word.
Jul 11 2007