Re: Dlang equivalent of #define/#ifdef : not... version

2021-04-20 Thread Dukc via Digitalmars-d-learn
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

2021-04-20 Thread Mike Parker via Digitalmars-d-learn

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

2021-04-20 Thread Steven Schveighoffer via Digitalmars-d-learn

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

2021-04-20 Thread Ali Çehreli via Digitalmars-d-learn

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

2021-04-20 Thread Simen Kjærås via Digitalmars-d-learn

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?

2021-04-20 Thread ichneumwn via Digitalmars-d-learn
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?

2021-04-20 Thread ichneumwn via Digitalmars-d-learn
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?

2021-04-20 Thread H. S. Teoh via Digitalmars-d-learn
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?

2021-04-20 Thread Steven Schveighoffer via Digitalmars-d-learn

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?

2021-04-20 Thread Steven Schveighoffer via Digitalmars-d-learn
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

2021-04-20 Thread mw via Digitalmars-d-learn

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

2021-04-20 Thread ichneumwn via Digitalmars-d-learn

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

2021-04-20 Thread JG via Digitalmars-d-learn

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

2021-04-20 Thread Andre Pany via Digitalmars-d-learn

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

2021-04-20 Thread JG via Digitalmars-d-learn

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?

2021-04-20 Thread MoonlightSentinel via Digitalmars-d-learn

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

2021-04-20 Thread Marcone via Digitalmars-d-learn

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

2021-04-20 Thread Mike Parker via Digitalmars-d-learn

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.