Re: Passing C++ class to DLL for callbacks from D (Steam)
Sample output: Initializing. User logged on: true Starting request. hid: 4838393704146785693 .. Request completed: NumberOfCurrentPlayers_t(1, 5828) Terminating. Not present: any indication that the registered callresult was executed.
Re: Passing C++ class to DLL for callbacks from D (Steam)
On Saturday, 9 June 2018 at 03:07:39 UTC, cc wrote: I've put together a simplified test program here (124KB): Here is a pastebin of the D source file updated with some additional comments at the end with the callback class definitions from the original header files https://pastebin.com/M8hDXt6L
Re: Passing C++ class to DLL for callbacks from D (Steam)
On Friday, 8 June 2018 at 07:32:54 UTC, evilrat wrote: On Friday, 8 June 2018 at 06:59:51 UTC, cc wrote: On Friday, 8 June 2018 at 02:52:10 UTC, Mike Parker wrote: 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? Tried wrapping the CImpl class in extern(C++), no luck.. tried final keyword on the methods too. Thanks though. Can you upload reduced example somewhere to play with? I've put together a simplified test program here (124KB): https://drive.google.com/uc?id=1VPxCcPShlYpGo8BggxniNlPH96iIRG8_=download The official SDK can be downloaded here (including the steam_api.dll if you don't want to use the one in the zip for security): https://partner.steamgames.com/doc/sdk Although it may require a developer account to download. Also I should note that Steam differentiates between "callbacks" (events that may be fired to the application that registers to listen for them at any time or multiple times) and "call results" (1:1 asynchronous requests, I believe). This test so far is using call results.
Re: I want delete or change class's member name on compile-time
On 06/08/2018 11:13 AM, Brian wrote: > Like: > > class A > { > string b; > string c; > } > > compile-time to: > > class A > { > string _b; > string c; > } > > or: > > class A > { > string c; > } > If these are your classes you can use static if or version: version = Z;// Can be provided as a compiler switch as well class A { version (X) { string b; } else version (Y) { string _b; } string c; } void main () { } Or with static if: class A { static if (some_compile_time_condition) { string _b; } else static if (...) { // ... } else { // ... } } Ali
Re: I want delete or change class's member name on compile-time
On 6/8/18 2:13 PM, Brian wrote: Like: class A { string b; string c; } compile-time to: class A { string _b; string c; } or: class A { string c; } Not possible in D. What you are looking for is an AST macro, and D does not have those. However, you can potentially create another type that mimics everything that A does except for one thing using compile-time introspection. But you won't be able to do that with the member functions. -Steve
File.put()
Writing a single value to binary file can be done in (at least) two ways. Let `f` be a `File`: ``` f.rawWrite(()[0 .. 1]); ``` or ``` f.lockingBinaryWriter.put(value); ``` The former way is little talked about, the latter is not even documented. As far as I can see, the latter resolves to the former [1] if we disregard locking, mode switching and keeping a reference count (on Windows). Shouldn't there be a `File.put()` method for the case where you already know that the file is locked and in the right mode? The trick to convert a single value to a range so it can be feeded to `rawWrite` may not be obvious to everyone. Or have I just overlooked the obvious way for writing single values? [1] https://github.com/dlang/phobos/blob/v2.080.1/std/stdio.d#L3102
Re: Confusion/trying to understand CTFE keywords
On Friday, June 08, 2018 03:51:11 David Bennett via Digitalmars-d-learn wrote: > 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. No, they're not equivalent. That template definition just forces the value to be calculated at compile time. It doesn't change anything about the variable itself. Making the variable static means that there is only one instance of the variable across all calls to the function. So, its address is not within the stack of the function. Given that the variable is immutable and thus cannot be changed means that that distinction doesn't matter a lot in this case, but there's still a difference. And if you make the variables mutable, it makes a huge difference. e.g auto n = ctfe!(foo()); vs static n = foo(); In both cases, the value is calculated at compile time, but in the first case, you get a unique copy for each function call that does not exist beyond that function call, whereas in the second case, it's reused for each function call, so if you mutate it, subsequent calls will see the mutated value (which would not be true if the variable weren't static). > 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? Sort of but not really. enums are just names for compile-time values. As such, they have to be calculated at compile time. static variables on the other hand really have nothing to do with compile time per se. It's just that they have a single location in memory for the entire thread of the program. So, they get initialized when the thread is created and not when the function is called and as such have to have their initial value known at compile time unless a static constructor is used to initialize them. They're either intialized with the init value for their type or the value that they're given when declared. The exact same thing happens with member variables. e.g. struct S { int i = foo(); } makes it so that S.init.i is whatever value was the result of foo. If the struct has a constructor, then that's the value of i before the constructor is called. The init value for the struct must be known at compile time, so any direct initialization is done at compile time (whereas if none is done, then the init value for the type of the member variable is used). If the member variable is const or immutable, then if it's directly initialized, then it can't be assigned in the constructor, and if it's not directly initialized, its init value is overwritten by the constructor and isn't really used. But regardless, the init value must be known at compile time, which means that any direct initialization must be calculated at compile time. So, the fact that static variables get their intial values at compile time is just because of how they're intialized, not because of static specifically being designed with compile-time anything in mind. The result is that you then have a variable whose initial value was determined at compile time and then can be manipulated at runtime (assuming that it's mutable), but the key thing about static variables is their lifetime, not that they're initialized at compile time. If what you're really looking for is to calculate the value of a local variable at compile-time, you're better off using an enum and then initializing the local variable with the enum than using a static variable. The only reason to use a static variable is if you specifically want a variable whose lifetime is for the duration of the thread rather than the duration of the function call. If you're using static just to get the value calculated at compile time, you're increasing how much memory your thread takes up when there really isn't a good reason to do so. - Jonathan M Davis
Re: Confusion/trying to understand CTFE keywords
On Friday, 8 June 2018 at 17:09:54 UTC, H. S. Teoh wrote: I would, if I had the time to spare to make such a chart. Perhaps you (or somebody here) could do it? It *is* a wiki, after all. Y'all don't have to wait for me to get around to it, the edit button is right there. T Fair point.
Re: WTF! new in class is static?!?!
On Thursday, June 07, 2018 22:43:50 aliak via Digitalmars-d-learn wrote: > 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] Not necessarily. It's the pointer equivalent of what the OP did with a mutable class reference, and I was using it for demonstrative purposes. The mutable class reference case didn't used to compile (it used to have to be immutable). This example is just the logic of what happens if it's legal with pointers too. If it hasn't been changed to be legal with pointers like it has been with classes, then that's arguably a good thing. - Jonathan M Davis
I want delete or change class's member name on compile-time
Like: class A { string b; string c; } compile-time to: class A { string _b; string c; } or: class A { string c; }
Re: Confusion/trying to understand CTFE keywords
On Fri, Jun 08, 2018 at 02:57:26PM +, jmh530 via Digitalmars-d-learn wrote: [...] > May I suggest that you add a flow chart that gives a very high level > understanding of the compiler steps. Like how Rust's introduction to > MIR has: > https://blog.rust-lang.org/2016/04/19/MIR.html I would, if I had the time to spare to make such a chart. Perhaps you (or somebody here) could do it? It *is* a wiki, after all. Y'all don't have to wait for me to get around to it, the edit button is right there. T -- Give a man a fish, and he eats once. Teach a man to fish, and he will sit forever.
Re: Confusion/trying to understand CTFE keywords
On Fri, Jun 08, 2018 at 02:36:01PM +, Gopan via Digitalmars-d-learn wrote: > On Friday, 8 June 2018 at 05:10:16 UTC, H. S. Teoh wrote: > > 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 > > > > > > > Hi Teoh, Your article is a killer! A must read for all serious > users. Can't we navigate to this article from the DLang site? (I > mean, if I don't know the specific url, how can I reach there?) [...] The goal is to eventually put this article among the main articles on the wiki, but there are some loose ends that I need to clean up, and I just haven't had the time to work on it. Perhaps I should just invite others here to edit the article, clean it up, and publish it, instead of letting it linger forever as a userpage. I just don't have enough spare time right now to do it justice. T -- What do you call optometrist jokes? Vitreous humor.
allMembers trait does not work correctly for packages during recursion
I'm trying to create a template class that can be parameterized with a module and will be able to serialize and deserialize (and more) all types in that module and submodules that have a specific UDA or superclass. My initial idea was to do a recursive search for types by starting from the module parameter and applying allMembers recursively to submodules and packages to find all types. There is a problem though: meta/search.d (For searching the classes): https://pastebin.com/BHJwnFYB meta/seq.d (For some AliasSeq operations): https://pastebin.com/frq9JLrM net/test.d (For testing): https://pastebin.com/4XiUBZMb Here the net.test imports meta.search. If I parameterize TransitiveSearchUDA with net.test, it finds struct X and calls TransitiveSearchUDA for the package meta, but the allMembers trait for that package comes up empty. It does however return the members of the meta package somewhat correctly (it does not return the search module, only the contents of the search module) if I directly call allMembers on it from net.test without TransitiveSearchUDA. What is the problem here? Or is there a better way to perform my task?
Re: Confusion/trying to understand CTFE keywords
On Friday, 8 June 2018 at 05:10:16 UTC, H. S. Teoh wrote: 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 May I suggest that you add a flow chart that gives a very high level understanding of the compiler steps. Like how Rust's introduction to MIR has: https://blog.rust-lang.org/2016/04/19/MIR.html
Re: Confusion/trying to understand CTFE keywords
On Friday, 8 June 2018 at 05:10:16 UTC, H. S. Teoh wrote: 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 Hi Teoh, Your article is a killer! A must read for all serious users. Can't we navigate to this article from the DLang site? (I mean, if I don't know the specific url, how can I reach there?) Thanks, Gopan
Re: how to sort the container Array from std.container
On 06/08/2018 10:52 AM, Flaze07 wrote: ah...well thank you, well...I did finds another way, but it is probably better to use linearRemove I used arr = make!( Array!uint )( remove( arr[], 2 ); so linearRemove is probably better Instead of creating a new array, you could update the length of the existing one: arr.length = remove(arr[], 2).length; But linearRemove is probably clearer.
Re: how to sort the container Array from std.container
On Wednesday, 6 June 2018 at 14:46:56 UTC, ag0aep6g wrote: On 06/06/2018 04:20 PM, Flaze07 wrote: hmm, and sorry for asking more, what about removing an element from it ? I found no remove operation that can remove from the middle ( removeAny and removeBack both removes the latest element, linearRemove receive Array!uint...which don't know how to provide ) I think removeKey would be the container primitive for that. I don't know if there's a reason why it isn't implemented for Array. Maybe it's just an oversight. You can use linearRemove like this: import std.container.array: Array; import std.stdio: writeln; void main() { Array!int a = [1, 2, 100, 200, 300, 3, 4]; a.linearRemove(a[2 .. 5]); /* Removes elements at indices 2, 3, and 4. */ writeln(a[]); /* Prints "[1, 2, 3, 4]". */ } ah...well thank you, well...I did finds another way, but it is probably better to use linearRemove I used arr = make!( Array!uint )( remove( arr[], 2 ); so linearRemove is probably better
Re: Runtime introspection, or how to get class members at runtime Fin D
On Friday, 8 June 2018 at 08:06:27 UTC, Arafel wrote: On Thursday, 7 June 2018 at 13:07:21 UTC, evilrat wrote: 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. Yes, that's what I understood from looking at it, but perhaps I was just missing something. I wonder though how the "agressive mode" would work with separate compilation / dlopen'ed libraries. Perhaps I should give it a try and see what happens. 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. Well, I'm already tightly coupled to linux, so this is not a big concern for me :-) I'll keep trying, as I said, my intention was to let plugin writers do it as easily as possible, but well, adding some kind of "register" function might be necessary in the end... A. Yep. Like I said probably the easiest to use way is to place single call in each module. And there probably no other solution, because modules creates sort of isolated graph via imports. And I am not aware of any way to get list of modules passed in with compiler invocation to perform some sort of centralized one-liner registration. But anyway look at this, might give some tips on how it can be done mixin https://github.com/Circular-Studios/Dash/blob/b7d589ad4ca8993445c136b6a4ae170932bb7962/source/dash/components/component.d#L208 (note that it uses static this() - module constructor. I think this behavior was changed around 2015-2016 and now it will cause cyclic dependency errors when modules with ctors import each other) usage https://github.com/Circular-Studios/Dash/blob/b7d589ad4ca8993445c136b6a4ae170932bb7962/source/dash/components/lights.d#L12
Re: Using stdin/out in a windows application bugs only when compiled to 64bit.
On Friday, 8 June 2018 at 03:08:21 UTC, Mike Franklin wrote: 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. Using main() instead of WinMain() did the trick too. Also it's simpler, so I choose this way. But it was also important to learn about the SUBSYSTEM and ENTRY linker options. Thank you all very much!
Re: Runtime introspection, or how to get class members at runtime Fin D
On Thursday, 7 June 2018 at 13:07:21 UTC, evilrat wrote: 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. Yes, that's what I understood from looking at it, but perhaps I was just missing something. I wonder though how the "agressive mode" would work with separate compilation / dlopen'ed libraries. Perhaps I should give it a try and see what happens. 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. Well, I'm already tightly coupled to linux, so this is not a big concern for me :-) I'll keep trying, as I said, my intention was to let plugin writers do it as easily as possible, but well, adding some kind of "register" function might be necessary in the end... A.
Re: Using stdin/out in a windows application bugs only when compiled to 64bit.
On Friday, 8 June 2018 at 02:44:13 UTC, Mike Parker wrote: ...you can get it with this: dmd -m64 -L/SUBSYSTEM:console -L/ENTRY:WinMainCRTStartup foo.d Thank You! It works with LDC -m64 as well. And now that I repaired my VCRedist2015 the bat file test (my second code example) is working too.
Re: Passing C++ class to DLL for callbacks from D (Steam)
On Friday, 8 June 2018 at 06:59:51 UTC, cc wrote: On Friday, 8 June 2018 at 02:52:10 UTC, Mike Parker wrote: 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? Tried wrapping the CImpl class in extern(C++), no luck.. tried final keyword on the methods too. Thanks though. Can you upload reduced example somewhere to play with?
Re: Passing C++ class to DLL for callbacks from D (Steam)
On Friday, 8 June 2018 at 02:52:10 UTC, Mike Parker wrote: 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? Tried wrapping the CImpl class in extern(C++), no luck.. tried final keyword on the methods too. Thanks though.
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.