www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Re: any tool to at least partially convert C++ to D (htod for source

reply Eldar Insafutdinov <e.insafutdinov gmail.com> writes:
Walter Bright Wrote:

 Eldar Insafutdinov wrote:
 The issue is that we need it in a performance critical part of QtD.
 The library mixes in static constructors to initialise user-defined
 classes. This means that we can't use it when user code is in cyclic
 dependency. static constructors are very useful, but giving a
 possibility to override it's current behaviour would make them
 applicable to more use-cases(if you look into that bug report,
 another person was trying to use them exactly as we do, and faced the
 same problems).

I hear you. I'll try to come up with a better solution.

Thank you very much.
Mar 11 2010
next sibling parent Jacob Carlborg <doob me.com> writes:
On 3/11/10 11:22, Eldar Insafutdinov wrote:
 Walter Bright Wrote:

 Eldar Insafutdinov wrote:
 The issue is that we need it in a performance critical part of QtD.
 The library mixes in static constructors to initialise user-defined
 classes. This means that we can't use it when user code is in cyclic
 dependency. static constructors are very useful, but giving a
 possibility to override it's current behaviour would make them
 applicable to more use-cases(if you look into that bug report,
 another person was trying to use them exactly as we do, and faced the
 same problems).

I hear you. I'll try to come up with a better solution.

Thank you very much.

I really hope a solution can be found.
Mar 11 2010
prev sibling parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2010-03-11 05:22:38 -0500, Eldar Insafutdinov 
<e.insafutdinov gmail.com> said:

 Walter Bright Wrote:
 
 Eldar Insafutdinov wrote:
 The issue is that we need it in a performance critical part of QtD.
 The library mixes in static constructors to initialise user-defined
 classes. This means that we can't use it when user code is in cyclic
 dependency. static constructors are very useful, but giving a
 possibility to override it's current behaviour would make them
 applicable to more use-cases(if you look into that bug report,
 another person was trying to use them exactly as we do, and faced the
 same problems).

I hear you. I'll try to come up with a better solution.

Thank you very much.

Yes, thank you. I'd like to point out that the trick of creating a separate module to initialize another one is not much safer than C++ static initialization. Take for instance std.stdio which it is initialized by std.stdiobase's static constructor. If your module import std.stdio and attempt to use the standard input/output/error streams in a static constructor, there is no guaranty that std.stdiobase static constructor will have been called before yours (unless you also import std.stdiobase). It might end up crashing depending on link order. So it's a clever trick allowing you to bypass the safety checks, but it's still dangerous, and it's not usable for templates and mixins. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Mar 11 2010
parent reply Max Samukha <spambox d-coding.com> writes:
Michel Fortin wrote:

 
 I'd like to point out that the trick of creating a separate module to 
 initialize another one is not much safer than C++ static initialization.
 
 Take for instance std.stdio which it is initialized by std.stdiobase's 
 static constructor. If your module import std.stdio and attempt to use 
 the standard input/output/error streams in a static constructor, there 
 is no guaranty that std.stdiobase static constructor will have been 
 called before yours (unless you also import std.stdiobase). It might end 
 up crashing depending on link order.

If your module imports std.stdio, std.stdiobase's static constructor is guaranteed to run before your module's static constructors because your module depends on std.stdiobase indirectly via std.studio.
 
 So it's a clever trick allowing you to bypass the safety checks, but 
 it's still dangerous, and it's not usable for templates and mixins.

Mar 11 2010
parent reply Walter Bright <newshound1 digitalmars.com> writes:
Max Samukha wrote:
 Michel Fortin wrote:
 
 I'd like to point out that the trick of creating a separate module to 
 initialize another one is not much safer than C++ static initialization.

 Take for instance std.stdio which it is initialized by std.stdiobase's 
 static constructor. If your module import std.stdio and attempt to use 
 the standard input/output/error streams in a static constructor, there 
 is no guaranty that std.stdiobase static constructor will have been 
 called before yours (unless you also import std.stdiobase). It might 
 end up crashing depending on link order.

If your module imports std.stdio, std.stdiobase's static constructor is guaranteed to run before your module's static constructors because your module depends on std.stdiobase indirectly via std.studio.

Max is correct. This is not a problem, because the dependency checking is transitive.
Mar 11 2010
parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2010-03-11 13:26:17 -0500, Walter Bright <newshound1 digitalmars.com> said:

 Max Samukha wrote:
 Michel Fortin wrote:
 
 
 I'd like to point out that the trick of creating a separate module to 
 initialize another one is not much safer than C++ static initialization.
 
 Take for instance std.stdio which it is initialized by std.stdiobase's 
 static constructor. If your module import std.stdio and attempt to use 
 the standard input/output/error streams in a static constructor, there 
 is no guaranty that std.stdiobase static constructor will have been 
 called before yours (unless you also import std.stdiobase). It might 
 end up crashing depending on link order.

If your module imports std.stdio, std.stdiobase's static constructor is guaranteed to run before your module's static constructors because your module depends on std.stdiobase indirectly via std.studio.

Max is correct. This is not a problem, because the dependency checking is transitive.

Ah, you're right indeed. I thought it was std.stdiobase that imported std.stdio, but its the reverse so it's a little better. Still, std.stdiobase uses this clever external definition to avoid a circular import: extern(C) void std_stdio_static_this(); This hack is basically just a bypass of the circular dependency check for one module. If more than one module use it, you're at risk of having the behaviour dependent on the link order. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Mar 11 2010
parent reply Walter Bright <newshound1 digitalmars.com> writes:
Michel Fortin wrote:
 Ah, you're right indeed. I thought it was std.stdiobase that imported 
 std.stdio, but its the reverse so it's a little better.
 
 Still, std.stdiobase uses this clever external definition to avoid a 
 circular import:
 
     extern(C) void std_stdio_static_this();
 
 This hack is basically just a bypass of the circular dependency check 
 for one module. If more than one module use it, you're at risk of having 
 the behaviour dependent on the link order.

No, the transitive nature of the dependency checking insures it is NOT dependent on link order.
Mar 11 2010
parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2010-03-11 21:35:42 -0500, Walter Bright <newshound1 digitalmars.com> said:

 Michel Fortin wrote:
 Ah, you're right indeed. I thought it was std.stdiobase that imported 
 std.stdio, but its the reverse so it's a little better.
 
 Still, std.stdiobase uses this clever external definition to avoid a 
 circular import:
 
     extern(C) void std_stdio_static_this();
 
 This hack is basically just a bypass of the circular dependency check 
 for one module. If more than one module use it, you're at risk of 
 having the behaviour dependent on the link order.

No, the transitive nature of the dependency checking insures it is NOT dependent on link order.

What I meant is that this is dependent on link order (and I tested it): module a; import a_base; import b; int ai; extern(C) void initA() { ai = bi+2; } module a_base; extern(C) void initA(); static this() { initA(); } module b; import b_base; import a; int bi; extern(C) void initB() { bi = ai+4; } module b_base; extern(C) void initB(); static this() { initB(); } module main; import b; import a; import std.stdio; void main() { writeln("a.ai = ", ai, " b.bi = ", bi); } -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Mar 12 2010
parent Walter Bright <newshound1 digitalmars.com> writes:
Michel Fortin wrote:
 What I meant is that this is dependent on link order (and I tested it):
 
 module a;
 import a_base;
 import b;
 int ai;
 extern(C) void initA() { ai = bi+2; }
 
 module a_base;
 extern(C) void initA();
 static this() { initA(); }
 
 module b;
 import b_base;
 import a;
 int bi;
 extern(C) void initB() { bi = ai+4; }
 
 module b_base;
 extern(C) void initB();
 static this() { initB(); }
 
 module main;
 import b;
 import a;
 import std.stdio;
 void main() {
     writeln("a.ai = ", ai, "  b.bi = ", bi);
 }

True, when you use: extern (C) void initA(); instead of importing the module that declares initA(), you totally defeat the dependency checking, because the dependency checking is based on the import statements.
Mar 12 2010