Re: Passing C++ class to DLL for callbacks from D (Steam)
On Friday, 8 June 2018 at 00:55:35 UTC, cc wrote: I've defined it in D, as per https://dlang.org/spec/cpp_interface.html#classes : change this to class, or even abstract class as shown in example extern(C++) { interface CCallbackBase { //this() { m_nCallbackFlags = 0; m_iCallback = 0; } void Run( void *pvParam ); void Run( void *pvParam, bool bIOFailure, SteamAPICall_t hSteamAPICall ); int GetICallback(); int GetCallbackSizeBytes(); enum { k_ECallbackFlagsRegistered = 0x01, k_ECallbackFlagsGameServer = 0x02 } //uint8 m_nCallbackFlags; //int m_iCallback; //friend class CCallbackMgr; //CCallbackBase( const CCallbackBase& ); //CCallbackBase& operator=( const CCallbackBase& ); } } add extern(C++) to class as well to class CImpl : CCallbackBase { extern(C++) { this() { m_nCallbackFlags = 0; m_iCallback = 0; } void Run( void *pvParam ) { writeln("Run1"); } void Run( void *pvParam, bool bIOFailure, SteamAPICall_t hSteamAPICall ) { writeln("Run2"); } int GetICallback() { return m_iCallback; } int GetCallbackSizeBytes() { return NumberOfCurrentPlayers_t.sizeof; } // ordinarily use templates to determine what type struct ptr to return } uint8 m_nCallbackFlags; int m_iCallback; } you also may or may not need to mark non-virtual C++ methods as final. Of course I haven't used D for quite some time so I can be mistaken. But the lesson I learned the hard way is that in D for extern(C++) you don't use interface(it simply has no mapping to C++ types?), and for defining COM-interfaces use interface or it will bite you. I hope it helps.
Re: Confusion/trying to understand CTFE keywords
All this talk of CTFE and "compile-time", along with the confusion that arises from conflating everything done by the compiler into the blanket term "compile-time" makes me want to scream: https://wiki.dlang.org/User:Quickfur/Compile-time_vs._compile-time ;-) tl;dr: D's "compile-time" features consist of (at least) two distinct phases of code transformation: template expansion and CTFE, and having a proper understanding of exactly what they are and what the distinction between them is, will go a long way in clearing up a lot of the confusion commonly experienced by newcomers to D in regard to D's so-called "compile-time" features. --T
Is DWT busted?
I'm sorry about bringing this into here instead of DWT's subforum, but it's somewhat dead and hasn't been getting a lot of attention. I decided to finally play around with DWT today and tried to build the example. I got this: Performing "debug" build using /usr/bin/dmd for x86_64. dwt:base 1.0.1+swt-3.4.1: target for configuration "library" is up to date. dwt 1.0.1+swt-3.4.1: target for configuration "linux-gtk" is up to date. main ~master: building configuration "application"... Linking... To force a rebuild of up-to-date targets, run again with --force. Running ./main Program exited with code -11 I'm on Pop!_OS (basically Ubuntu), x64, DMD 2.079.0. Every library they ask for is installed. I tried cloning the source and building their snippets, and none of them work. Other people have apparently had this same problem for the past few months, and none of them find a solution. What's going on here? IDK if this is any help, but here's the backtrace according to gdb: https://pastebin.com/Xd46YwwP
Re: Confusion/trying to understand CTFE keywords
On Thursday, 7 June 2018 at 04:58:40 UTC, Jonathan M Davis wrote: It would be trivial enough to create a wrapper template so that you can do something like immutable n = ctfe!(foo()); e.g. template ctfe(alias value) { enum ctfe = value; } Would this be equivalent to using static immutable? static immutable n = foo(); In this case both the compiletime and runtime values were calculated using cfte. Also back to the OP the way I think of enum, static types is like this: alias and enum create compiletime stuff from compiletime stuff. static creates runtime stuff from compiletime stuff. Is that view valid in most cases?
Re: Using stdin/out in a windows application bugs only when compiled to 64bit.
On Thursday, 7 June 2018 at 19:19:55 UTC, realhet wrote: Hi, The following narrow test program works fine when compiled with DMD to 32bit target: import std.stdio, core.sys.windows.windows, core.runtime; extern(Windows) int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int iCmdShow) { Runtime.initialize; writeln("Hello"); stdout.flush; //exception readln; //exception return 0; } It shows the console window and waits for user input at readln. If I try to compile this to 64bit target or with LDC (both 32 and 64) it gets privileged instruction exception at stdout.flush. If I comment out flush then it fails at readln. Is there a way to fix this? I don't wanna lose the console window even on 64bit. Thanks! You might be running into this issue: https://issues.dlang.org/show_bug.cgi?id=6880 I recall similar issues with a project I was working on, but I don't remember all the details now. Anyway, I ended up with this in the end. https://github.com/JinShil/Dsus2/blob/b08c66c6a6efb46134c409aac9f1c600d62f99fa/Dsus2/main.d#L300-L331 Mike
Re: Passing C++ class to DLL for callbacks from D (Steam)
On Friday, 8 June 2018 at 00:55:35 UTC, cc wrote: class CImpl : CCallbackBase { extern(C++) { If anyone has any insight to provide it would be greatly appreciated, thanks! I've not used any of the C++ interfacing features yet, but my understanding is the extern(C++) has to apply to the class declaration itself, not only the member functions: extern(C++) class CImpl : CCallbackBase { Does that make a difference?
Re: Using stdin/out in a windows application bugs only when compiled to 64bit.
On Thursday, 7 June 2018 at 19:19:55 UTC, realhet wrote: Hi, The following narrow test program works fine when compiled with DMD to 32bit target: import std.stdio, core.sys.windows.windows, core.runtime; extern(Windows) int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int iCmdShow) { Runtime.initialize; writeln("Hello"); stdout.flush; //exception readln; //exception return 0; } It shows the console window and waits for user input at readln. If I try to compile this to 64bit target or with LDC (both 32 and 64) it gets privileged instruction exception at stdout.flush. If I comment out flush then it fails at readln. I get no exceptions with this code, but if I run if I compile with no flags, it prints hello and waits for input. With -m32mscoff or -m64, there's no output. If I run from Windows Explorer, the no-flag version pops up a console, prints and waits, while the -m32mscoff and do nothing. As Steven mentioned earlier, this is a runtime issue. The standard I/O streams are not available in the MSVC runtime by default when compiling as a GUI application. You don't have to enable any flags to get that -- it's automatic when WinMain is present. The DititalMars runtime, which is what you get with the default compile, apparently does initialize the standard I/O streams and makes sure the console pops up when you write to it. Is there a way to fix this? I don't wanna lose the console window even on 64bit. If you want to keep WinMain and still have the console stuff available from the start with the MSVC runtime, you can get it with this: dmd -m64 -L/SUBSYSTEM:console -L/ENTRY:WinMainCRTStartup foo.d With this (for -m32mscoff as well), the above code runs the same as it does with the DigitalMars runtime.
Passing C++ class to DLL for callbacks from D (Steam)
Hello, I'm attempting to interface with the Steam API DLL in D and running into some trouble working with callbacks. I'm aware there's already a project here http://derelict-steamworks.dub.pm/ but it seems to have not yet addressed the same issue. Steam provides ways to poll for whether an asynchronous request has completed yet and retrieve the results, but what I am trying to implement is receiving actual callbacks from the API. Just for reference, I've gotten simple callbacks working in other APIs (passing a D function pointer to a C function and having it be called back), and the other basic Steam functions that don't deal with callbacks all work fine (defined in D as extern(C)). Here's where I'm running into trouble: Definitions in C++ headers provided by Steam: typedef uint64 SteamAPICall_t; S_API void S_CALLTYPE SteamAPI_RegisterCallResult( class CCallbackBase *pCallback, SteamAPICall_t hAPICall ); S_API void S_CALLTYPE SteamAPI_UnregisterCallResult( class CCallbackBase *pCallback, SteamAPICall_t hAPICall ); class CCallbackBase { public: CCallbackBase() { m_nCallbackFlags = 0; m_iCallback = 0; } // don't add a virtual destructor because we export this binary interface across dll's virtual void Run( void *pvParam ) = 0; virtual void Run( void *pvParam, bool bIOFailure, SteamAPICall_t hSteamAPICall ) = 0; int GetICallback() { return m_iCallback; } virtual int GetCallbackSizeBytes() = 0; protected: enum { k_ECallbackFlagsRegistered = 0x01, k_ECallbackFlagsGameServer = 0x02 }; uint8 m_nCallbackFlags; int m_iCallback; friend class CCallbackMgr; private: CCallbackBase( const CCallbackBase& ); CCallbackBase& operator=( const CCallbackBase& ); }; It's actually more complex than that as it has templated classes that inherit from that base so that there is a different template for each expected struct that gets returned from various async requests. I'm trying to get the simplest possible scenario working first and hoping I'm not missing anything, but I don't actually understand how I'm supposed to work with the C++ objects enough really to be sure. Here's how I've defined it in D, as per https://dlang.org/spec/cpp_interface.html#classes : alias ulong SteamAPICall_t; extern(C) { void SteamAPI_RegisterCallResult(CCallbackBase pCallback, SteamAPICall_t hAPICall); void SteamAPI_UnregisterCallResult(CCallbackBase pCallback, SteamAPICall_t hAPICall); } extern(C++) { interface CCallbackBase { //this() { m_nCallbackFlags = 0; m_iCallback = 0; } void Run( void *pvParam ); void Run( void *pvParam, bool bIOFailure, SteamAPICall_t hSteamAPICall ); int GetICallback(); int GetCallbackSizeBytes(); enum { k_ECallbackFlagsRegistered = 0x01, k_ECallbackFlagsGameServer = 0x02 } //uint8 m_nCallbackFlags; //int m_iCallback; //friend class CCallbackMgr; //CCallbackBase( const CCallbackBase& ); //CCallbackBase& operator=( const CCallbackBase& ); } } class CImpl : CCallbackBase { extern(C++) { this() { m_nCallbackFlags = 0; m_iCallback = 0; } void Run( void *pvParam ) { writeln("Run1"); } void Run( void *pvParam, bool bIOFailure, SteamAPICall_t hSteamAPICall ) { writeln("Run2"); } int GetICallback() { return m_iCallback; } int GetCallbackSizeBytes() { return NumberOfCurrentPlayers_t.sizeof; } // ordinarily use templates to determine what type struct ptr to return } uint8 m_nCallbackFlags; int m_iCallback; } Which then gets called later on as: auto cbk = new CImpl(); cbk.m_iCallback = NumberOfCurrentPlayers_t.k_iCallback; auto hid = SteamAPI_ISteamUserStats_GetNumberOfCurrentPlayers(...); SteamAPI_RegisterCallResult(cbk, hid); And then every frame SteamAPI_RunCallbacks(); runs, which is supposed to fire off the callbacks. I've also tried using abstract class instead of interface. My expectation of what's supposed to happen is that one of those Run() functions gets called at some point. However, it never does (even though I can poll to determine the call has actually completed). I'm hoping the problem is I'm simply not passing the right expected type of data to the registration function and/or haven't defined the interface in D properly (I admit I have very little idea how the C++ is working anymore, including what those private methods are for), and not an issue with utilizing the API itself, since I doubt there's anyone I could ask on the Steam end of things about interfacing with D. My gut feeling is I'm doing something very incorrect/stupid on the definition end of things, I understand passing function pointers to C++ functions that intend to call back well enough but I'm confused about this concept of passing "class SomeClass
Re: Using stdin/out in a windows application bugs only when compiled to 64bit.
On Thursday, 7 June 2018 at 23:25:45 UTC, Steven Schveighoffer wrote: ... The WinMain exported function works alone well and on 32bit it also does the console. On 64 I also tried AllocConsole, but fail. I get the Console handle with GetConsoleHandle, it sends back a nonzero value. But as I play with it, now I can broke it even when I only use main() as export. This bat file runs(dmd and visual-d installed to default c:\d path) (It only affects LDC & win64) echo void main(){ import std.stdio; writeln(123); } > test.d ldmd2 -vcolumns -c -op -allinst -w -m64 -release -O -inline -boundscheck=off test.d call msvcenv amd64 cd c:\d link /LIBPATH:C:\d\ldc2\lib64 /OUT:test.exe /MACHINE:X64 /MAP legacy_stdio_definitions.lib test.obj druntime-ldc.lib phobos2-ldc.lib msvcrt.lib test.exe And when I want to run the same exe from outside with totalcommander, it brings up an "application was unable to start: 0xc0fb exception in a small window o.O. UPDATE: The exe only starts when "msvcenv.bat amd64" was called before. That enironment setter bat file is needed for the exe as well o.O I really thank you for trying to help me. Maybe that other different runtime you mentioned is using environment variables to be able to start up. Tomorrow I will test it.
Re: Using stdin/out in a windows application bugs only when compiled to 64bit.
On 6/7/18 7:16 PM, realhet wrote: On Thursday, 7 June 2018 at 19:42:05 UTC, Steven Schveighoffer wrote: Are you just compiling the 32-bit dmd version with default flags? Yes, no flags at all and it defaults to a 32bit target. I can use the console and able to make windows, and able to setup an opengl window too. The console (stdin/stdout/SetConsoleAttribute) stuff crashes only when I compile to 64bit with DMD or to 32/64 with LDC. So that is definitely dmc initializing the console window in that context. If so, it's likely an issue with MSVC runtime library not being properly set up. DMD 32 bit by default uses DMC runtime. I just tried to put up msvcrt2017 runtime but doesnt solved the issue. Sorry, I'm not familiar with Windows enough to help. To verify, use the switch -m32mscoff to do 32-bit result but link against MSVC library. Compiling this way is impossible: It can't link even basic stuff like GetDC(). Also lost with this one. I know this isn't really an answer, but it at least narrows it down. Been a while since I did windows development, but it sounds like you are trying to print to or read from a console that isn't open. A windows program that has gui-only flag doesn't by default allocate a console. Most likely dmc just does it for you. To be honest I don't use gui-only flag as I don't even know about where to put it :D (.def file maybe, but I don't). I use core.Runtime.initialize only. That is enough in 32bit but not in 64bit. I don't know what happens nowadays. I literally haven't tried to build non-console Windows applications since like 2008 or so? I thought it was a linker flag, but I'm not sure. My goal is to have a fully functional exe that contains every necessary things inside it. So far this is given when I use DMD and compile to win32. The error I'm getting is not a 'friendly' exception. It is a privileged instruction crash. Well, you are telling the linker, when you create your WinMain function that you are handling all the runtime setup yourself, and you are not using a console. So somehow you have to initialize the console. Alternatively, you can define extern(C) main function, and handle the D initialization from there. Is there a reason you want the D runtime but don't want to have D initialize it for you? And it caused only by adding the -m64 option, not changing anything else. The linking is done by DMD itself also. (If I link with msvcenv.bat && MSLink.exe, it produces also the same fail.) Just to be clear, it's not the 32-bit vs 64-bit, it has to do with which C runtime you are using. -Steve
Re: Using stdin/out in a windows application bugs only when compiled to 64bit.
On Thursday, 7 June 2018 at 19:42:05 UTC, Steven Schveighoffer wrote: Are you just compiling the 32-bit dmd version with default flags? Yes, no flags at all and it defaults to a 32bit target. I can use the console and able to make windows, and able to setup an opengl window too. The console (stdin/stdout/SetConsoleAttribute) stuff crashes only when I compile to 64bit with DMD or to 32/64 with LDC. If so, it's likely an issue with MSVC runtime library not being properly set up. DMD 32 bit by default uses DMC runtime. I just tried to put up msvcrt2017 runtime but doesnt solved the issue. To verify, use the switch -m32mscoff to do 32-bit result but link against MSVC library. Compiling this way is impossible: It can't link even basic stuff like GetDC(). I know this isn't really an answer, but it at least narrows it down. Been a while since I did windows development, but it sounds like you are trying to print to or read from a console that isn't open. A windows program that has gui-only flag doesn't by default allocate a console. Most likely dmc just does it for you. To be honest I don't use gui-only flag as I don't even know about where to put it :D (.def file maybe, but I don't). I use core.Runtime.initialize only. That is enough in 32bit but not in 64bit. My goal is to have a fully functional exe that contains every necessary things inside it. So far this is given when I use DMD and compile to win32. The error I'm getting is not a 'friendly' exception. It is a privileged instruction crash. And it caused only by adding the -m64 option, not changing anything else. The linking is done by DMD itself also. (If I link with msvcenv.bat && MSLink.exe, it produces also the same fail.)
Re: WTF! new in class is static?!?!
On Thursday, 7 June 2018 at 23:08:22 UTC, Steven Schveighoffer wrote: On 6/7/18 6:58 PM, DigitalDesigns wrote: On Thursday, 7 June 2018 at 21:57:17 UTC, Steven Schveighoffer wrote: On 6/7/18 5:07 PM, DigitalDesigns wrote: class A; class B { A a = new A(); } auto b1 = new B(); auto b2 = new B(); assert(b1.a == b2.a)!! Yep, long-standing issue: https://issues.dlang.org/show_bug.cgi?id=2947 Almost a decade old! wait! everyone is saying it is a feature! So, which is it, a feature or a bug?!?!? It's a feature that you can assign a static initializer to a class or struct member and have that work at compile time (using CTFE). But when it's a reference to mutable data, it's a bug. Just the idea that you have implicitly shared data if you create instances in multiple threads should make it obviously a bug. Even back then it was a debate, look at the bug report. But it's definitely a bug. Just hard to close since it will probably break a lot of code. -Steve I would expect that using a static initialize would not break as much code going from immutable to mutable than the other way around. Someone should have been smart enough to create a static new so both methods could have been implemented in a sane way.
Re: WTF! new in class is static?!?!
On 6/7/18 6:58 PM, DigitalDesigns wrote: On Thursday, 7 June 2018 at 21:57:17 UTC, Steven Schveighoffer wrote: On 6/7/18 5:07 PM, DigitalDesigns wrote: class A; class B { A a = new A(); } auto b1 = new B(); auto b2 = new B(); assert(b1.a == b2.a)!! Yep, long-standing issue: https://issues.dlang.org/show_bug.cgi?id=2947 Almost a decade old! wait! everyone is saying it is a feature! So, which is it, a feature or a bug?!?!? It's a feature that you can assign a static initializer to a class or struct member and have that work at compile time (using CTFE). But when it's a reference to mutable data, it's a bug. Just the idea that you have implicitly shared data if you create instances in multiple threads should make it obviously a bug. Even back then it was a debate, look at the bug report. But it's definitely a bug. Just hard to close since it will probably break a lot of code. -Steve
Re: WTF! new in class is static?!?!
On Thursday, 7 June 2018 at 21:57:17 UTC, Steven Schveighoffer wrote: On 6/7/18 5:07 PM, DigitalDesigns wrote: class A; class B { A a = new A(); } auto b1 = new B(); auto b2 = new B(); assert(b1.a == b2.a)!! Yep, long-standing issue: https://issues.dlang.org/show_bug.cgi?id=2947 Almost a decade old! -Steve wait! everyone is saying it is a feature! So, which is it, a feature or a bug?!?!?
Re: WTF! new in class is static?!?!
On Thursday, 7 June 2018 at 21:32:54 UTC, Jonathan M Davis wrote: struct S { int* ptr = new int(42); } Is that supposed to compile? -> https://run.dlang.io/is/SjUEOu Error: cannot use non-constant CTFE pointer in an initializer &[42][0]
Re: WTF! new in class is static?!?!
On 06/07/2018 11:26 PM, Ethan wrote: The spec isn't clear on this but it uses the same rules as struct field initialisation, ie it's defined once and copied to each instance on creation. https://dlang.org/spec/struct.html#default_struct_init It says there that "The default initializers may not contain references to mutable data." DMD enforces that for pointers to primitives, but not for arrays, class objects, or even pointers to structs: struct S { int* p = new int(1); /* Error: cannot use non-constant CTFE pointer in an initializer */ int[] a = [1, 2, 3]; /* no error */ C c = new C; /* no error */ S2* s = new S2; /* no error */ } class C { int x = 4; } struct S2 { int x = 5; } Seems inconsistent to me.
Re: WTF! new in class is static?!?!
On 6/7/18 5:07 PM, DigitalDesigns wrote: class A; class B { A a = new A(); } auto b1 = new B(); auto b2 = new B(); assert(b1.a == b2.a)!! Yep, long-standing issue: https://issues.dlang.org/show_bug.cgi?id=2947 Almost a decade old! -Steve
Re: WTF! new in class is static?!?!
On Thursday, 7 June 2018 at 21:07:26 UTC, DigitalDesigns wrote: I'm glad I finally found this out! This is not typical behavior in most languages is it? I don't think most languages allow this, and D used to not allow it either, but then CTFE got class support and it got enabled. If you understand how it works, it is sometimes useful... But, it is confusing for a *lot* of people so it might make sense to ban it again - or at least make it more obvious that this is what you intended when you write it.
Re: WTF! new in class is static?!?!
On Thursday, 7 June 2018 at 21:07:26 UTC, DigitalDesigns wrote: class A; class B { A a = new A(); } auto b1 = new B(); auto b2 = new B(); assert(b1.a == b2.a)!! I'm glad I finally found this out! This is not typical behavior in most languages is it? I'd expect it to be translated to something like class B { A a; this() { a = new A(); } } In C# it is different, can't remember if it is different in C++. This has caused bugs in my code because the fields are all pointing to the same data when I expected them to each have unique data ;/ This method is error prone and the behavior should be reversed, it should not break the majority of code. If one wants the current behavior then static new could be used or something else. The spec looks pretty clear to me on that point https://dlang.org/spec/class.html#field-init Besides, defining behaviour at construction is what constructors are for, I wouldn't expect anything outside a constructor to happen when an object is constructed. So while I understand that other languages may (successfully for them) do things differently I don't think I'd like a breaking change for that.
Re: WTF! new in class is static?!?!
On Thursday, 7 June 2018 at 21:07:26 UTC, DigitalDesigns wrote: class A; class B { A a = new A(); } auto b1 = new B(); auto b2 = new B(); assert(b1.a == b2.a)!! I'm glad I finally found this out! This is not typical behavior in most languages is it? I'd expect it to be translated to something like class B { A a; this() { a = new A(); } } In C# it is different, can't remember if it is different in C++. This has caused bugs in my code because the fields are all pointing to the same data when I expected them to each have unique data ;/ This method is error prone and the behavior should be reversed, it should not break the majority of code. If one wants the current behavior then static new could be used or something else. If you want a new one use a constructor call. initalizers are support to be static, this only works because ctfe supports newing classes.
Re: WTF! new in class is static?!?!
On Thursday, June 07, 2018 21:07:26 DigitalDesigns via Digitalmars-d-learn wrote: > class A; > > class B > { > A a = new A(); > } > > auto b1 = new B(); > auto b2 = new B(); > > assert(b1.a == b2.a)!! > > > I'm glad I finally found this out! This is not typical behavior > in most languages is it? > > I'd expect it to be translated to something like > > class B > { > A a; > this() > { > a = new A(); > } > } > > In C# it is different, can't remember if it is different in C++. > This has caused bugs in my code because the fields are all > pointing to the same data when I expected them to each have > unique data ;/ > > This method is error prone and the behavior should be reversed, > it should not break the majority of code. If one wants the > current behavior then static new could be used or something else. Well, if that compiles now with a non-immutable class object, then that was a language improvement. In any case, yes, the class object would be shared across all instances of the class. _Every_ type in D has an init value that they get default-initialized to before the constructor is run (assuming that the type even has a constructor). In the case of both classes and structs, whatever the member variables are directly initialized with make up the init value. So, if you have something like struct S { int i = 42; } then every instance of S will start with the value of 42 for i, and if you have something like struct S { int i = 42; this(int j) { i = j; } } then S.i is 42 before the constructor is run and will then be whatever it gets assigned to in the constructor after the constructor has run. The situation with classes is exactly the same as structs except that you don't have direct access to the init value (since you only ever deal with class references, not the classes themselves). One key result of this is that the class object is fully initialized to its init value for its exact type before _any_ constructors are called, so you don't get that problem that C++ has where the object isn't fully its correct type until all of the constructors have been called (so calling virtual functions from a class constructor in D actually works, unlike C++). All of this is quite clean with value types, but in the case of member variables that are pointers, dynamic arrays, or reference types that would mean that if you had something like struct S { int* ptr = new int(42); } every instance of S would have the same exact value for S.ptr, which can be surprising and is why it's sometimes been suggested that it not be legal to directly initialize member variables with mutable, non-value types. However, historically, this really only mattered for dynamic arrays, because originally it wasn't legal to directly initialize any member variable that was a pointer or reference, because the compiler and runtime weren't sophisticated enough to handle it. Several years ago, it was made possible to directly initialize immutable class references, but that doesn't really cause any problems, since sharing an immutable object doesn't cause problems. However, if it's now possible for the init value of an object to contain a mutable class reference or pointer, then the problem does get worse, and arguably, it becomes more critical to just make it illegal in the case of member variables in order to avoid the surprises (and bugs) that come when folks misunderstand what it really means to directly initialize a member variable in D. In any case, the way that D works here is a direct result of how init values work, and it really doesn't make sense for it to work any other way. At most, it would make sense to simply make it illegal to directly initialize types where it would be a problem. - Jonathan M Davis
Re: WTF! new in class is static?!?!
On Thursday, 7 June 2018 at 21:07:26 UTC, DigitalDesigns wrote: assert(b1.a == b2.a)!! The spec isn't clear on this but it uses the same rules as struct field initialisation, ie it's defined once and copied to each instance on creation. https://dlang.org/spec/struct.html#default_struct_init
Re: Confusion/trying to understand CTFE keywords
On Thursday, June 07, 2018 11:31:13 jmh530 via Digitalmars-d-learn wrote: > On Wednesday, 6 June 2018 at 22:19:58 UTC, Jonathan M Davis wrote: > > On Wednesday, June 06, 2018 18:18:16 jmh530 via > > > > Digitalmars-d-learn wrote: > >> On Monday, 4 June 2018 at 03:18:05 UTC, Jonathan M Davis wrote: > >> > [snip] > >> > > >> > If you haven't yet, I'd suggest reading > >> > >> Would make a good blog series? > > > > What would make a good blog series? Something talking about > > CTFE? > > > > - Jonathan M Davis > > I meant that stuff describing the nuances and motivations between > static/enum/etc. Maybe more tutorial or something on the wiki > than blog series? It's the type of thing that isn't obvious to > someone new to D, but you explain very well. Better to save it in > some place easy to find than let it get buried in Learn. I probably should do more write-ups of stuff somewhere so that I can point people to them, but for better or worse, I haven't done much of that. I've mostly just answered questions here or at stackoverflow. I did finally get my website set up though (http://jmdavisprog.com) so that I have somewhere to post articles and whatnot, but I haven't done much with it yet. Sadly, the only reason that I finally got around to setting it up was that I was pretty much forced to in order to have a place to put the documentation for dxml. Doing more useful write-ups has been on my todo list for ages but mostly hasn't ended up as a priority with everything else on my plate - which is arguably a bit dumb given how often I ultimately end up spending a bunch of time answering questions on D.Learn even when I theoretically try to not spend a lot of time replying to posts. - Jonathan M Davis
WTF! new in class is static?!?!
class A; class B { A a = new A(); } auto b1 = new B(); auto b2 = new B(); assert(b1.a == b2.a)!! I'm glad I finally found this out! This is not typical behavior in most languages is it? I'd expect it to be translated to something like class B { A a; this() { a = new A(); } } In C# it is different, can't remember if it is different in C++. This has caused bugs in my code because the fields are all pointing to the same data when I expected them to each have unique data ;/ This method is error prone and the behavior should be reversed, it should not break the majority of code. If one wants the current behavior then static new could be used or something else.
Re: Using stdin/out in a windows application bugs only when compiled to 64bit.
On 6/7/18 3:19 PM, realhet wrote: Hi, The following narrow test program works fine when compiled with DMD to 32bit target: import std.stdio, core.sys.windows.windows, core.runtime; extern(Windows) int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int iCmdShow) { Runtime.initialize; writeln("Hello"); stdout.flush; //exception readln; //exception return 0; } It shows the console window and waits for user input at readln. If I try to compile this to 64bit target or with LDC (both 32 and 64) it gets privileged instruction exception at stdout.flush. If I comment out flush then it fails at readln. Is there a way to fix this? I don't wanna lose the console window even on 64bit. Thanks! Are you just compiling the 32-bit dmd version with default flags? If so, it's likely an issue with MSVC runtime library not being properly set up. DMD 32 bit by default uses DMC runtime. To verify, use the switch -m32mscoff to do 32-bit result but link against MSVC library. I know this isn't really an answer, but it at least narrows it down. Been a while since I did windows development, but it sounds like you are trying to print to or read from a console that isn't open. A windows program that has gui-only flag doesn't by default allocate a console. Most likely dmc just does it for you. -Steve
Using stdin/out in a windows application bugs only when compiled to 64bit.
Hi, The following narrow test program works fine when compiled with DMD to 32bit target: import std.stdio, core.sys.windows.windows, core.runtime; extern(Windows) int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int iCmdShow) { Runtime.initialize; writeln("Hello"); stdout.flush; //exception readln; //exception return 0; } It shows the console window and waits for user input at readln. If I try to compile this to 64bit target or with LDC (both 32 and 64) it gets privileged instruction exception at stdout.flush. If I comment out flush then it fails at readln. Is there a way to fix this? I don't wanna lose the console window even on 64bit. Thanks!
Re: Runtime introspection, or how to get class members at runtime Fin D
On Thursday, 7 June 2018 at 12:32:26 UTC, Arafel wrote: Thanks for all the answers! Is it possible to register, say, a base class, and have all the subclasses then registered automatically? My idea would be to make it as transparent as possible for the plugin implementation, and also not having to depend on it. A. I don't think so. It clearly states that children must mixin too, which can mean it just grabs symbols in scope only, and base class has no way of knowing about its subclasses. It also has "agressive mode" that will make metadata for all public symbols(?) it can walk, this may or may not be helpful depending on your requirements. Besides there is no way(not that I am aware of) to make self registering stuff happen, you still need to call it somewhere. The most transparent option is probably just doing a mixin in each module that performs registration of all module symbols in module ctor. The point is that there is absolute requirement to make explicit call for that, be it a module ctor mixin, class mixin or even user provided registration both at compile time or run time. But since it is MIT licensed you can probably use the code as the starting point and adjust to your own needs. BTW plug-ins is something that is right now possible on Linux(not sure about support on other *NIX systems), but in a very primitive form on Windows. This is related to DLL support issues(such as type information not being passed across process/DLL boundaries), these issues also may include runtime issues as well such as inability to delegate the GC, which will mean there will be 2(or more) concurrent running GC's. But again I am not aware of the current situation.
Re: Why does using zlib without pragma(lib, ...) work?
On 08/06/2018 12:25 AM, tipdbmp wrote: What other libraries (if any) are part of Phobos? That is pretty much it.
Re: Runtime introspection, or how to get class members at runtime Fin D
Thanks for all the answers! Is it possible to register, say, a base class, and have all the subclasses then registered automatically? My idea would be to make it as transparent as possible for the plugin implementation, and also not having to depend on it. A. There is a library that creates reflection metadata for you. [1] It seems a bit outdated and has some not-that-obvious compilation errors(for example getting ctor and callling it with runtime known type, or some other non template stuff), but other than that seems to be working (note that I didn't thorougly tested it, but its unittests succeeds on DMD 2.080 for both Windows x86 mscoff & x64 ) [1] https://code.dlang.org/packages/witchcraft
Re: Why does using zlib without pragma(lib, ...) work?
What other libraries (if any) are part of Phobos?
Re: Why does using zlib without pragma(lib, ...) work?
On 07/06/2018 11:47 PM, tipdbmp wrote: The following compiles without pragma(lib, ...): extern(C) { const(char)* zlibVersion(); } void main() { const(char)* sz = zlibVersion(); } It has already been compiled in as part of Phobos.
Why does using zlib without pragma(lib, ...) work?
The following compiles without pragma(lib, ...): extern(C) { const(char)* zlibVersion(); } void main() { const(char)* sz = zlibVersion(); }
Re: Runtime introspection, or how to get class members at runtime Fin D
On Wednesday, 6 June 2018 at 13:28:02 UTC, Arafel wrote: I know it might not be the most idiomatic D, but as somebody with mostly a Java background (with some C and just a bit of C++) it seems something really straightforward to me: myObject.getClass().getFields() [2]. Also, I know I could add some UDA or even crawl the modules and have this information generated automatically at compilation time and added to the type itself in a member, and I might even end up doing it, but honestly, I think it's something that the language should provide in a kind of easy / accessible way. Powerful as compile-time introspection is, I think runtime shouldn't be forgotten either :-) Thanks, A. [1]: https://dlang.org/library/object/type_info__class.html [2]: https://docs.oracle.com/javase/8/docs/api/java/lang/Class.html#getFields-- There is a library that creates reflection metadata for you. [1] It seems a bit outdated and has some not-that-obvious compilation errors(for example getting ctor and callling it with runtime known type, or some other non template stuff), but other than that seems to be working (note that I didn't thorougly tested it, but its unittests succeeds on DMD 2.080 for both Windows x86 mscoff & x64 ) [1] https://code.dlang.org/packages/witchcraft
Re: Confusion/trying to understand CTFE keywords
On Wednesday, 6 June 2018 at 22:19:58 UTC, Jonathan M Davis wrote: On Wednesday, June 06, 2018 18:18:16 jmh530 via Digitalmars-d-learn wrote: On Monday, 4 June 2018 at 03:18:05 UTC, Jonathan M Davis wrote: > [snip] > > If you haven't yet, I'd suggest reading Would make a good blog series? What would make a good blog series? Something talking about CTFE? - Jonathan M Davis I meant that stuff describing the nuances and motivations between static/enum/etc. Maybe more tutorial or something on the wiki than blog series? It's the type of thing that isn't obvious to someone new to D, but you explain very well. Better to save it in some place easy to find than let it get buried in Learn.