Re: Dlang equivalent of #define/#ifdef : not... version
On Tuesday, 20 April 2021 at 23:58:46 UTC, Steven Schveighoffer wrote: static if(i_am_a_feature) { ... } This would be correct if `i_am_a_feature` would be always defined, just set to `false` if not existent. But I think the idea was to not define the symbol at all if feature does not exists. In that case, the condition should be `static if(is(typeof(i_am_a_feature)))`.
Re: Local library with dub
On Tuesday, 20 April 2021 at 18:43:28 UTC, JG wrote: This still leaves open the question of how to include a version of such a library in another project via dub. Execute `dub add-local` followed by the path to the project's root directory (the directory containing the `dub.json/sdl`) and a version number in semver format. ``` dub add-local path 0.1.0 ``` Then you can use the package just as you would any other dub dependency.
Re: Dlang equivalent of #define/#ifdef : not... version
On 4/20/21 2:57 PM, ichneumwn wrote: Hi, Trying to convert a C header to D. The underlying package exists in different versions and may or may not expose certain functionality (modules/extensions). One should check at compile time that the header provides the relevant definitions, through #ifdef, and do a further run-time check to confirm the functionality is really present. It is the compile time check that I am finding tricky to do/emulate. .h : #define i_am_a_feature 1 enum i_am_a_feature = true; The C-code uses this define as a guard: .c : #ifdef i_am_a_feature static if(i_am_a_feature) { ... } So my questions: - is there a module-crossing equivalent of "version"? enum isn't exactly "module crossing", but it's defined within the module, which means you can look at it from elsewhere. - if not, is there some way I could test for the existence of the enum can_i_test_for_this? A SymbolExists!() or ModuleHasSymbol!() or ModuleHasMember!() ? This is surprisingly tricky. A template will not accept a symbol by alias that doesn't exist, and if you pass in a string and test, it will test if that template can see the symbol, not your code. You can probably do it inline: static if(__traits(compiles, {alias x = doesThisExist;})); -Steve
Re: Dlang equivalent of #define/#ifdef : not... version
On 4/20/21 3:03 PM, Simen Kjærås wrote: On Tuesday, 20 April 2021 at 18:57:46 UTC, ichneumwn wrote: So my questions: - is there a module-crossing equivalent of "version"? mw covered this. There's more documentation here: https://dlang.org/spec/version.html#version https://dlang.org/dmd-windows.html#switch-version - if not, is there some way I could test for the existence of the enum can_i_test_for_this? A SymbolExists!() or ModuleHasSymbol!() or ModuleHasMember!() ? __traits(hasMember, features, "i_am_not_a_feature") This is actually what std.traits.hasMember does, but for some reason it can't take a module as its first argument. -- Simen Could it be because __MODULE__ is string, requiring mixin? The following prints 'true': enum i_am_not_a_feature = 42; pragma(msg, __traits(hasMember, mixin(__MODULE__), "i_am_not_a_feature")); Ali
Re: Dlang equivalent of #define/#ifdef : not... version
On Tuesday, 20 April 2021 at 18:57:46 UTC, ichneumwn wrote: So my questions: - is there a module-crossing equivalent of "version"? mw covered this. There's more documentation here: https://dlang.org/spec/version.html#version https://dlang.org/dmd-windows.html#switch-version - if not, is there some way I could test for the existence of the enum can_i_test_for_this? A SymbolExists!() or ModuleHasSymbol!() or ModuleHasMember!() ? __traits(hasMember, features, "i_am_not_a_feature") This is actually what std.traits.hasMember does, but for some reason it can't take a module as its first argument. -- Simen
Re: write once type?
On Tuesday, 20 April 2021 at 20:04:17 UTC, Steven Schveighoffer wrote: I just realized, this is Rebindable, or tail-const. (I don't need the head to be truly const, I just need to be able to copy into a const-referring thing). I currently am using a pointer, which is working, but I prefer not to use it, and it is not general enough. -Steve Ah, you found it - I was looking up the reference for it and you replied in the mean-time. Ignore my answer :)
Re: write once type?
On Tuesday, 20 April 2021 at 19:56:33 UTC, Steven Schveighoffer wrote: I have had the need in some cases to *maybe* set a const value inside a loop. One can sometimes abstract this into a lambda function, but sometimes this is not possible (e.g. if the loop is static). Not only that, but I may also want to keep processing the loop and do something different if the value has already been set instead of returning immediately, which necessitates a second loop. My use case is I have a property that is const inside a set of types, and I want to verify that they all have the same value, and extract what that value is. I'm wondering if anyone has a "Write once" type, that is, a type that allows you to write it exactly once, and is treated like initialization on first setting (i.e. allows writing to previously unused const data). This type has to decide at runtime whether it has been set. So it would kind of be like Nullable!T, but Nullable doesn't allow setting when the T is const. Optional!T doesn't work either. -Steve Not quite your use case, I think, but std.typecons.Rebindable at least allows you to bind a new const(object). Not write once though. I think I found that after a hint of its existence in https://forum.dlang.org/thread/orpbvvjspibfpitnn...@forum.dlang.org
Re: write once type?
On Tue, Apr 20, 2021 at 03:56:33PM -0400, Steven Schveighoffer via Digitalmars-d-learn wrote: [...] > I'm wondering if anyone has a "Write once" type, that is, a type that > allows you to write it exactly once, and is treated like > initialization on first setting (i.e. allows writing to previously > unused const data). Maybe a const class? The reference is null until you initialize it by allocating a new object and initializing it in the ctor. But sounds like you want a value type instead. Technically, allocating a const class involves the GC assigning some region of memory to the class, initializing it, then casting it to const. So I'd imagine that the by-value equivalent would require a const cast somewhere, probably in a @trusted block if you want it to work with @safe. Which means that probably you'll need a @trusted cast somewhere in your implementation. So perhaps something like this: struct WriteOnce(T) { const T payload; const bool isSet; void opAssign(U : T)(U data) in (!isSet) { assert(!isSet); @trusted() { *(cast()&payload) = data; *(cast()&isSet) = true; }(); } } T -- Prosperity breeds contempt, and poverty breeds consent. -- Suck.com
Re: write once type?
On 4/20/21 3:56 PM, Steven Schveighoffer wrote: I have had the need in some cases to *maybe* set a const value inside a loop. One can sometimes abstract this into a lambda function, but sometimes this is not possible (e.g. if the loop is static). Not only that, but I may also want to keep processing the loop and do something different if the value has already been set instead of returning immediately, which necessitates a second loop. My use case is I have a property that is const inside a set of types, and I want to verify that they all have the same value, and extract what that value is. I'm wondering if anyone has a "Write once" type, that is, a type that allows you to write it exactly once, and is treated like initialization on first setting (i.e. allows writing to previously unused const data). This type has to decide at runtime whether it has been set. So it would kind of be like Nullable!T, but Nullable doesn't allow setting when the T is const. Optional!T doesn't work either. I just realized, this is Rebindable, or tail-const. (I don't need the head to be truly const, I just need to be able to copy into a const-referring thing). I currently am using a pointer, which is working, but I prefer not to use it, and it is not general enough. -Steve
write once type?
I have had the need in some cases to *maybe* set a const value inside a loop. One can sometimes abstract this into a lambda function, but sometimes this is not possible (e.g. if the loop is static). Not only that, but I may also want to keep processing the loop and do something different if the value has already been set instead of returning immediately, which necessitates a second loop. My use case is I have a property that is const inside a set of types, and I want to verify that they all have the same value, and extract what that value is. I'm wondering if anyone has a "Write once" type, that is, a type that allows you to write it exactly once, and is treated like initialization on first setting (i.e. allows writing to previously unused const data). This type has to decide at runtime whether it has been set. So it would kind of be like Nullable!T, but Nullable doesn't allow setting when the T is const. Optional!T doesn't work either. -Steve
Re: Dlang equivalent of #define/#ifdef : not... version
On Tuesday, 20 April 2021 at 18:57:46 UTC, ichneumwn wrote: So my questions: - is there a module-crossing equivalent of "version"? https://dub.pm/package-format-json.html Configurations / versions { ... "name": "somepackage", "configurations": [ { "name": "metro-app", "targetType": "executable", "platforms": ["windows"], "versions": ["MetroApp"], "libs": ["d3d11"] }, { "name": "desktop-app", "targetType": "executable", "platforms": ["windows"], "versions": ["DesktopApp"], "libs": ["d3d9"] }, { "name": "glut-app", "targetType": "executable", "versions": ["GlutApp"] } ] }
Dlang equivalent of #define/#ifdef : not... version
Hi, Trying to convert a C header to D. The underlying package exists in different versions and may or may not expose certain functionality (modules/extensions). One should check at compile time that the header provides the relevant definitions, through #ifdef, and do a further run-time check to confirm the functionality is really present. It is the compile time check that I am finding tricky to do/emulate. .h : #define i_am_a_feature 1 The C-code uses this define as a guard: .c : #ifdef i_am_a_feature What would the the D equivalent? This is my attempt so far: features.d: import std.traits; private enum capabilities { i_am_a_feature } template supported(string member) { enum bool supported = hasMember!(capabilities, member); } version = vs_i_am_a_feature; enum can_i_test_for_this; and use.d: import features; import std.stdio; void main() { static if (supported!("i_am_a_feature")) { writeln("Feature 1!"); } static if (supported!("i_am_not_a_feature")) { writeln("Feature 2!"); } version(vs_i_am_a_feature) { writeln("If only I worked"); } } This produces "Feature 1!", so the supported() path works, but is a bit of a round-about way and all "capability flags" need to put in that single enum capabilities instead of being allowed to be scattered across the features.d module. As is documented, "version" does not cross the module boundary. So my questions: - is there a module-crossing equivalent of "version"? - if not, is there some way I could test for the existence of the enum can_i_test_for_this? A SymbolExists!() or ModuleHasSymbol!() or ModuleHasMember!() ? Cheers
Re: Local library with dub
On Tuesday, 20 April 2021 at 18:11:18 UTC, Andre Pany wrote: On Tuesday, 20 April 2021 at 17:15:15 UTC, JG wrote: Hi I want to put some code together in a local library that is then used by several other projects. I am running into a few problems. Firstly when I try and configure the code to be a library (dub init, add d files to source, and remove source/app.d - perhaps this wrong) dub test no longer seems to work? Secondly I am having problems getting dub to add the library code to other projects. It seems to work if I run dub add-local path/to/library and then add the appropriate dependencies to the projects dub.json file. However, I didn't manage to find documentation that explains exactly how this should work. Also there seems to be some mention getting this to work with versions (in the documentation about dub add-path), which I couldn't follow. Does anyone know in more detail how this works or how I can find out? You need to add 2 configurations. The first configuration is used automatically when you execute `dub build`. Just name the config `debug` with targetType `library`. Add a second configuration with name `unittest` and targetType `executable` and attribute `mainSourceFile` pointing to a module containing your main function for your test. For example name this module `testapp.d`. The module `testapp.d` you need to exclude in your configuration `debug` using attribute `excludeSourceFiles`. The configuration `unittest` is automatically used when you execute `dub test`. Kind regards Andre Thank you very much. In case someone wants more specific instructions: (a) add a file source/test.d containing: void main(){} (b) add configurations to dub.json: "configurations": [ { "name": "debug", "excludedSourceFiles": ["source/test.d"], "targetType": "library"}, { "name": "unittest", "mainSourceFile": "source/test.d", "targetType": "executable"}] This still leaves open the question of how to include a version of such a library in another project via dub.
Re: Local library with dub
On Tuesday, 20 April 2021 at 17:15:15 UTC, JG wrote: Hi I want to put some code together in a local library that is then used by several other projects. I am running into a few problems. Firstly when I try and configure the code to be a library (dub init, add d files to source, and remove source/app.d - perhaps this wrong) dub test no longer seems to work? Secondly I am having problems getting dub to add the library code to other projects. It seems to work if I run dub add-local path/to/library and then add the appropriate dependencies to the projects dub.json file. However, I didn't manage to find documentation that explains exactly how this should work. Also there seems to be some mention getting this to work with versions (in the documentation about dub add-path), which I couldn't follow. Does anyone know in more detail how this works or how I can find out? You need to add 2 configurations. The first configuration is used automatically when you execute `dub build`. Just name the config `debug` with targetType `library`. Add a second configuration with name `unittest` and targetType `executable` and attribute `mainSourceFile` pointing to a module containing your main function for your test. For example name this module `testapp.d`. The module `testapp.d` you need to exclude in your configuration `debug` using attribute `excludeSourceFiles`. The configuration `unittest` is automatically used when you execute `dub test`. Kind regards Andre
Local library with dub
Hi I want to put some code together in a local library that is then used by several other projects. I am running into a few problems. Firstly when I try and configure the code to be a library (dub init, add d files to source, and remove source/app.d - perhaps this wrong) dub test no longer seems to work? Secondly I am having problems getting dub to add the library code to other projects. It seems to work if I run dub add-local path/to/library and then add the appropriate dependencies to the projects dub.json file. However, I didn't manage to find documentation that explains exactly how this should work. Also there seems to be some mention getting this to work with versions (in the documentation about dub add-path), which I couldn't follow. Does anyone know in more detail how this works or how I can find out?
Re: How to skip class/function when using -HC flag to generate C++ headers?
On Monday, 19 April 2021 at 17:43:34 UTC, evilrat wrote: On Monday, 19 April 2021 at 17:37:31 UTC, MoonlightSentinel wrote: Omit the modules from your blacklist when generating the header file (allthough that requires rerunning dmd) Ok thanks, well, time for new dub subconfig. Or... maybe at least pre-build step for that specific module. That being said, it might be worthwhile to add a flag to customize the minimum visibility for declarations (currently it only omits private declarations)
Re: win64 DLL stdout printing after main process completes
On Monday, 19 April 2021 at 14:55:03 UTC, cc wrote: I'm not sure if this is something unique to D or not, but I've having a minor issue where stdout output from a DLL (either via printf or phobos std.stdio write) is not displayed until after the main process has completed. I'm making a project based around the example at https://wiki.dlang.org/Win32_DLLs_in_D which I've heard is a little out of date but I've gotten it working nonetheless. I have the following project files: ```d // mydll.d module mydll; import core.runtime; import core.stdc.stdio; import core.stdc.stdlib; import core.sys.windows.windows; extern(Windows) BOOL DllMain(HINSTANCE hInstance, ULONG ulReason, LPVOID pvReserved) { switch (ulReason) { case DLL_PROCESS_ATTACH: printf("[dll] DLL_PROCESS_ATTACH\n"); Runtime.initialize(); break; case DLL_PROCESS_DETACH: printf("[dll] DLL_PROCESS_DETACH\n"); Runtime.terminate(); break; case DLL_THREAD_ATTACH: printf("[dll] DLL_THREAD_ATTACH\n"); return false; case DLL_THREAD_DETACH: printf("[dll] DLL_THREAD_DETACH\n"); return false; default: } return true; } export int MyDLL_Test() { printf("[dll] MyDLL_Test\n"); return 5; } static this() { printf("[dll] static this for mydll\n"); } static ~this() { printf("[dll] static ~this for mydll\n"); } ``` ```d // mydll.di module mydll; export int MyDLL_Test(); ``` ```d // main.d import mydll; pragma(lib, "mydll.lib"); import core.sys.windows.windows; void main() { printf("[Main] Start\n"); scope(exit) printf("[Main] END\n"); int x = MyDLL_Test(); printf("[Main] x: %d\n", x); printf("[Main] Finished\n"); } ``` DLL compilation command line: `dmd -m64 -ofmydll.dll -L/DLL mydll.d mydll.def` Main command line: `rdmd -m64 main.d` And upon running, the output I receive is: ``` [Main] Start [Main] x: 5 [Main] Finished [Main] END [dll] DLL_PROCESS_ATTACH [dll] static this for mydll [dll] MyDLL_Test [dll] DLL_PROCESS_DETACH [dll] static ~this for mydll ``` I would expect the first three lines of dll output to precede the "[Main] x:" line at least. Is there something I'm doing wrong? Do I need to somehow pass a reference to the main stdio to the DLL's D runtime similar to how the GC can be shared? Hi, I use this function: // Function echo() void echo(T)(T text) nothrow {try {spawnShell("echo%s %s".format(text.to!string.strip() != "" ? "" : ".", text.to!string.replace(">","^>").replace("&","^&").replace("\n"," &&echo."))); } catch(Throwable){} } echo("This is not will wait the end to print.");
Re: win64 DLL stdout printing after main process completes
On Monday, 19 April 2021 at 14:55:03 UTC, cc wrote: I would expect the first three lines of dll output to precede the "[Main] x:" line at least. Is there something I'm doing wrong? Do I need to somehow pass a reference to the main stdio to the DLL's D runtime similar to how the GC can be shared? I just compiled and executed your code locally here's the output I saw without using any flushing: ``` [dll] DLL_PROCESS_ATTACH [dll] static this for mydll [Main] Start [dll] MyDLL_Test [Main] x: 5 [Main] Finished [Main] END [dll] DLL_PROCESS_DETACH [dll] static ~this for mydll ``` My command lines: ``` dmd -m64 -L/DLL mydll.d dmd -m64 main.d ``` I dropped the -of because that's redundant. The .def file isn't needed, but I did compile with one based on the example you linked. It gave me warnings about all of the directives being ignored because they're unsupported on the target platform (I also had to change MyDLL_Test to extern(C), since I didn't use the D mangled name in the .def file) but the output was the same as above. I did have a problem, though, when I replaced printf with writeln/writefln, in that I got no output at all. I don't have time to dig deeper at the moment. Anway, I wonder what the difference is between our systems that we get different output. I'm on Windows 10, dmd 2.096.0, VS 2019. I suggest you also try compiling a comparable C example to see if what the output looks like: ```c // dllmain.c #define WINDOWS_LEAN_AND_MEAN #include BOOL DllMain(HINSTANCE hinst, ULONG reason, LPVOID reserved) { switch(reason) { case DLL_PROCESS_ATTACH: printf("[dll] DLL_PROCESS_ATTACH\n"); break; case DLL_PROCESS_DETACH: printf("[dll] DLL_PROCESS_DETACH\n"); break; case DLL_THREAD_ATTACH: printf("[dll] DLL_THREAD_ATTACH\n"); return 0; case DLL_THREAD_DETACH: printf("[dll] DLL_THREAD_DETACH\n"); return 0; default: break; } return 1; } __declspec(dllexport) int __cdecl MyDLL_Test(void) { printf("[dll] MyDLL_Test\n"); return 5; } ``` ```c // main.c #include #pragma comment(lib, "dllmain.lib") extern __declspec(dllimport) int __cdecl MyDLL_Test(void); int main(int argc, char** argv) { printf("[Main] Start\n"); int x = MyDLL_Test(); printf("[Main] x: %d\n", x); printf("[Main] Finished\n", x); printf("[Main] END\n"); } ``` In the *x64 Native Tools Command Prompt for VS 2019*: ``` cl /LD dllmain.c cl main.c ``` See if this produces the output you expect or if it looks the same as your D output.