Re: Linkage question

2022-01-24 Thread duser via Digitalmars-d-learn

On Monday, 24 January 2022 at 19:41:30 UTC, frame wrote:
On Monday, 24 January 2022 at 18:30:02 UTC, Stanislav Blinov 
wrote:


The difference is in how arguments are being passed, which you 
seem to have discovered already :)



Would like to know where the linkage format is defined, thx.


It should be here: https://dlang.org/spec/abi.html although 
IIRC it might not be 100% up to date.


Ah, yes. Thanks. Maybe I should read it more carefully =)

It claims that the D calling convention matches C. But it seems 
that the arguments are pushed in order whereas C does it in 
reverse order and the -218697648 value is indeed my 3rd string 
pointer.


that's a bug with dmd or the spec, arguments are currently passed 
in reverse order compared to C on 64-bit even though they should 
be the same


see:
https://issues.dlang.org/show_bug.cgi?id=20204
https://github.com/dlang/dmd/pull/13287
https://github.com/dlang/dlang.org/pull/3120


Re: unordered output of an associated array of associated arrays

2022-01-24 Thread H. S. Teoh via Digitalmars-d-learn
On Tue, Jan 25, 2022 at 02:46:43AM +, forkit via Digitalmars-d-learn wrote:
> On Tuesday, 25 January 2022 at 02:12:50 UTC, H. S. Teoh wrote:
> > 
> > That's the *easy* way out??  Try this instead:
> > 
> > aaTable.keys.sort.each!((k) {
> > aaTable[k].keys.sort.each!((kk) {
> > writefln("%s:%s:%s", k, kk, aaTable[k][kk]);
> > });
> > });
[...]
> surely, this is voodoo?  ;-)

No, this is D-doo.  We're here to do-D-doo. :-D


T

-- 
If you're not part of the solution, you're part of the precipitate.


Re: What is safe to do in an extern (C) function and how can I test this?

2022-01-24 Thread Jaime via Digitalmars-d-learn
On Tuesday, 25 January 2022 at 01:41:03 UTC, Steven Schveighoffer 
wrote:

On 1/24/22 8:31 PM, Jaime wrote:
Can I, for instance, safely call Fiber.yield in a C callback 
that I know will be run in a Fiber?


I would *imagine* it's fine, all the fiber context switch is 
doing (WRT the stack) is swapping out the fiber portion of the 
stack (i.e. back to the `Fiber.call` invokation), which should 
include the C stack portions as well.


There's a lot of low-level details in the Fiber.d file itself:

https://github.com/dlang/druntime/blob/e390ba7e0a1f80f15e72ca773fca7252057ba4c5/src/core/thread/fiber.d#L387

-Steve


On Tuesday, 25 January 2022 at 02:02:27 UTC, H. S. Teoh wrote:

I haven't tested this myself, but I *think* it should be OK.

One thing to watch out for, though, is the size of the Fiber's 
stack (this can be specified when you first create the Fiber).  
If the C part of the code uses up too much stack space (e.g. if 
somewhere in the C code it tries to allocate a large object on 
the stack), you may inadvertently overflow the Fiber's stack 
and cause a crash or abort. Increasing the stack size of the 
Fiber when it is created should fix this problem.



T


The insight and vote of confidence are much appreciated, you two. 
Steven, good call to check out the implementation of Fiber, I'll 
do that.


Re: unordered output of an associated array of associated arrays

2022-01-24 Thread forkit via Digitalmars-d-learn

On Tuesday, 25 January 2022 at 02:12:50 UTC, H. S. Teoh wrote:


That's the *easy* way out??  Try this instead:

aaTable.keys.sort.each!((k) {
aaTable[k].keys.sort.each!((kk) {
writefln("%s:%s:%s", k, kk, aaTable[k][kk]);
});
});


T


surely, this is voodoo?  ;-)


Re: unordered output of an associated array of associated arrays

2022-01-24 Thread H. S. Teoh via Digitalmars-d-learn
On Tue, Jan 25, 2022 at 02:04:26AM +, forkit via Digitalmars-d-learn wrote:
[...]
> // --
> module test;
> 
> import std;
> 
> void main()
> {
> auto aaTable =
>   ([
>"typeB" : [ 10002 : [1, 1, 0, 0, 0, 0, 0, 0],
>10001 : [1, 0, 0, 0, 0, 0, 0, 0]
>  ],
>"typeC" : [ 10007 : [1, 1, 1, 1, 1, 1, 0, 0],
>10006 : [1, 1, 1, 1, 1, 1, 0, 0]
>  ],
>"typeA" : [ 10005 : [1, 1, 1, 1, 1, 0, 0, 0],
>10003 : [1, 1, 1, 0, 0, 0, 0, 0],
>10004 : [1, 1, 1, 1, 0, 0, 0, 0]
>  ]
>   ]);
> 
> string[] orderedKeyPairSet;
> 
> foreach (key, pair; aaTable.byPair)
> {
> foreach(k, p; pair.byPair)
> orderedKeyPairSet ~= key ~ ":" ~ k.to!string ~ ":" ~
> p.to!string;
> }
> 
> orderedKeyPairSet.sort;
> 
> foreach(s; orderedKeyPairSet)
> writeln(s);

That's the *easy* way out??  Try this instead:

aaTable.keys.sort.each!((k) {
aaTable[k].keys.sort.each!((kk) {
writefln("%s:%s:%s", k, kk, aaTable[k][kk]);
});
});


T

-- 
Try to keep an open mind, but not so open your brain falls out. -- theboz


Re: unordered output of an associated array of associated arrays

2022-01-24 Thread forkit via Digitalmars-d-learn

On Tuesday, 25 January 2022 at 00:43:07 UTC, forkit wrote:


oh. thanks :-)

I will get that integrated into my example code, and will post 
again, once it's working (so others can  learn too)


ok.. so I took the easy way out ;-)

output is now ordered:

typeA:10003:[1, 1, 1, 0, 0, 0, 0, 0]
typeA:10004:[1, 1, 1, 1, 0, 0, 0, 0]
typeA:10005:[1, 1, 1, 1, 1, 0, 0, 0]
typeB:10001:[1, 0, 0, 0, 0, 0, 0, 0]
typeB:10002:[1, 1, 0, 0, 0, 0, 0, 0]
typeC:10006:[1, 1, 1, 1, 1, 1, 0, 0]
typeC:10007:[1, 1, 1, 1, 1, 1, 0, 0]


// --
module test;

import std;

void main()
{
auto aaTable =
  ([
   "typeB" : [ 10002 : [1, 1, 0, 0, 0, 0, 0, 0],
   10001 : [1, 0, 0, 0, 0, 0, 0, 0]
 ],
   "typeC" : [ 10007 : [1, 1, 1, 1, 1, 1, 0, 0],
   10006 : [1, 1, 1, 1, 1, 1, 0, 0]
 ],
   "typeA" : [ 10005 : [1, 1, 1, 1, 1, 0, 0, 0],
   10003 : [1, 1, 1, 0, 0, 0, 0, 0],
   10004 : [1, 1, 1, 1, 0, 0, 0, 0]
 ]
  ]);

string[] orderedKeyPairSet;

foreach (key, pair; aaTable.byPair)
{
foreach(k, p; pair.byPair)
orderedKeyPairSet ~= key ~ ":" ~ k.to!string ~ ":" ~ 
p.to!string;

}

orderedKeyPairSet.sort;

foreach(s; orderedKeyPairSet)
writeln(s);

}

// ---


Re: What is safe to do in an extern (C) function and how can I test this?

2022-01-24 Thread H. S. Teoh via Digitalmars-d-learn
On Tue, Jan 25, 2022 at 01:31:29AM +, Jaime via Digitalmars-d-learn wrote:
> **The lede**:
> 
> Can I, for instance, safely call Fiber.yield in a C callback that I
> know will be run in a Fiber?
> 
> The stack will look like:
> Thread
> |- Fiber in D runtime
> | |- Call into a C API (stays on same thread)
> | | |- Extern (C) callback (stays on same thread)
> | | | |- Fiber.yield <-- Is this OK?

I haven't tested this myself, but I *think* it should be OK.

One thing to watch out for, though, is the size of the Fiber's stack
(this can be specified when you first create the Fiber).  If the C part
of the code uses up too much stack space (e.g. if somewhere in the C
code it tries to allocate a large object on the stack), you may
inadvertently overflow the Fiber's stack and cause a crash or abort.
Increasing the stack size of the Fiber when it is created should fix
this problem.


T

-- 
Those who don't understand D are condemned to reinvent it, poorly. -- Daniel N


Re: What is safe to do in an extern (C) function and how can I test this?

2022-01-24 Thread Steven Schveighoffer via Digitalmars-d-learn

On 1/24/22 8:31 PM, Jaime wrote:

**The lede**:

Can I, for instance, safely call Fiber.yield in a C callback that I know 
will be run in a Fiber?


The stack will look like:
Thread
|- Fiber in D runtime
| |- Call into a C API (stays on same thread)
| | |- Extern (C) callback (stays on same thread)
| | | |- Fiber.yield <-- Is this OK?

Also, in general, is there a convenient way to know or test if 
particular C callbacks are safe? Or is it just case by case?


**The context I was gonna bury the lede in but thought better of it**:

So, I am a big lame novice. Don't worry, I know this already.

I'm trying to use gtk-d, but I don't even know how to use gtk, so I'm 
learning them both at once. Probably not a good idea, I know.


 From what I can tell so far, it seems like the way gtk works is you 
write your whole application in terms of gtk's event loop. I really 
don't want to do that, so -- and I realize this is probably an even 
worse idea, but I don't know the right thing to do -- I decided I'd try 
writing a worker thread class -- "Rope" -- and run gtk's event loop in a 
Rope.


A Rope runs its given task in a new Fiber in a new thread, and that 
thread repeatedly resumes the fiber and terminates when the fiber 
terminates, but, in the meantime, takes some time to act as an executor 
each time the fiber suspends, accepting work in std.concurrency messages 
and running it on the same thread as its main fiber. My thought was that 
this way, I can call gtk-d's API from any thread, and still have all the 
calls happen on the same thread that the event loop is running on, as 
the API requires.


All I needed, then, was some way to make gtk-d suspend the fiber it's 
running on, to give its rope some time to service external work. My 
first thought was to use glib.Timeout.Timeout.add and put Fiber.yield in 
the timeout callback. The potential problem: the timeout callback, of 
course, has to be extern (C).


Now, I could just drop the more general concept of Rope and rewrite it 
specifically for gtk, and drop the whole Fiber part, and instead 
directly put the calls to std.concurrency.receiveTimeout in the 
glib.Timeout.Timeout.add callback. Assuming, of course, receiveTimeout 
would be any safer to call from extern (C) than Fiber.yield would. But 
that's just the trouble, I can't guess which would be safer, and even a 
minimal test for this question seems daunting.


I would *imagine* it's fine, all the fiber context switch is doing (WRT 
the stack) is swapping out the fiber portion of the stack (i.e. back to 
the `Fiber.call` invokation), which should include the C stack portions 
as well.


There's a lot of low-level details in the Fiber.d file itself:

https://github.com/dlang/druntime/blob/e390ba7e0a1f80f15e72ca773fca7252057ba4c5/src/core/thread/fiber.d#L387

-Steve


What is safe to do in an extern (C) function and how can I test this?

2022-01-24 Thread Jaime via Digitalmars-d-learn

**The lede**:

Can I, for instance, safely call Fiber.yield in a C callback that 
I know will be run in a Fiber?


The stack will look like:
Thread
|- Fiber in D runtime
| |- Call into a C API (stays on same thread)
| | |- Extern (C) callback (stays on same thread)
| | | |- Fiber.yield <-- Is this OK?

Also, in general, is there a convenient way to know or test if 
particular C callbacks are safe? Or is it just case by case?


**The context I was gonna bury the lede in but thought better of 
it**:


So, I am a big lame novice. Don't worry, I know this already.

I'm trying to use gtk-d, but I don't even know how to use gtk, so 
I'm learning them both at once. Probably not a good idea, I know.


From what I can tell so far, it seems like the way gtk works is 
you write your whole application in terms of gtk's event loop. I 
really don't want to do that, so -- and I realize this is 
probably an even worse idea, but I don't know the right thing to 
do -- I decided I'd try writing a worker thread class -- "Rope" 
-- and run gtk's event loop in a Rope.


A Rope runs its given task in a new Fiber in a new thread, and 
that thread repeatedly resumes the fiber and terminates when the 
fiber terminates, but, in the meantime, takes some time to act as 
an executor each time the fiber suspends, accepting work in 
std.concurrency messages and running it on the same thread as its 
main fiber. My thought was that this way, I can call gtk-d's API 
from any thread, and still have all the calls happen on the same 
thread that the event loop is running on, as the API requires.


All I needed, then, was some way to make gtk-d suspend the fiber 
it's running on, to give its rope some time to service external 
work. My first thought was to use glib.Timeout.Timeout.add and 
put Fiber.yield in the timeout callback. The potential problem: 
the timeout callback, of course, has to be extern (C).


Now, I could just drop the more general concept of Rope and 
rewrite it specifically for gtk, and drop the whole Fiber part, 
and instead directly put the calls to 
std.concurrency.receiveTimeout in the glib.Timeout.Timeout.add 
callback. Assuming, of course, receiveTimeout would be any safer 
to call from extern (C) than Fiber.yield would. But that's just 
the trouble, I can't guess which would be safer, and even a 
minimal test for this question seems daunting.


Re: unordered output of an associated array of associated arrays

2022-01-24 Thread forkit via Digitalmars-d-learn

On Tuesday, 25 January 2022 at 00:39:05 UTC, H. S. Teoh wrote:



AA's are unordered containers. Do not rely on entries to appear 
in any specific order when you traverse an AA; it is 
implementation-dependent and may differ from OS to OS / 
platform to platform / sequence of operations performed on the 
AA since its initialization / phase of the moon. Any specific 
order that may appear in an AA is pure coincidence and may not 
appear again next time, or may only appear again at 11:59:59 
Feb 29 under a blue moon.


If you need entries in your AA in a specific order, extract 
them (or their keys) into an array then sort them yourself. 
E.g.:


string[string] myAA;
auto keys = myAA.keys;
sort(keys);
foreach (k; keys) {
... // now keys will be in the expected order
}


T


oh. thanks :-)

I will get that integrated into my example code, and will post 
again, once it's working (so others can  learn too)





Re: unordered output of an associated array of associated arrays

2022-01-24 Thread forkit via Digitalmars-d-learn

On Tuesday, 25 January 2022 at 00:23:40 UTC, forkit wrote:



another example:

output is:
typeA:
10001:[0, 0, 1, 1, 1, 1, 1, 1]
10002:[0, 0, 0, 1, 1, 1, 1, 1]
typeB:
10005:[0, 0, 0, 0, 0, 0, 1, 1]
10003:[0, 0, 0, 0, 1, 1, 1, 1]
10004:[0, 0, 0, 0, 0, 1, 1, 1]


// --

module test;

import std;

void main()
{
auto aaTable2 =
  ([
   "typeA" : [ 10001 : [0, 0, 1, 1, 1, 1, 1, 1],
   10002 : [0, 0, 0, 1, 1, 1, 1, 1] ],
   "typeB" : [ 10003 : [0, 0, 0, 0, 1, 1, 1, 1],
   10004 : [0, 0, 0, 0, 0, 1, 1, 1],
   10005 : [0, 0, 0, 0, 0, 0, 1, 1] ]
 ]);

foreach (topLevelKey, topLevelValue; aaTable2.byPair)
{
writefln("%s:", topLevelKey);

foreach(key, value; topLevelValue)
{
writefln("\t%s:%s", key, value);
}
}

}

//--





Re: unordered output of an associated array of associated arrays

2022-01-24 Thread H. S. Teoh via Digitalmars-d-learn
On Tue, Jan 25, 2022 at 12:23:40AM +, forkit via Digitalmars-d-learn wrote:
> so I'm trying to understand why the output of the code below, is in
> reverse order of the declaration (and how to fix it so that it outputs
> in an ordered way)

AA's are unordered containers. Do not rely on entries to appear in any
specific order when you traverse an AA; it is implementation-dependent
and may differ from OS to OS / platform to platform / sequence of
operations performed on the AA since its initialization / phase of the
moon. Any specific order that may appear in an AA is pure coincidence
and may not appear again next time, or may only appear again at 11:59:59
Feb 29 under a blue moon.

If you need entries in your AA in a specific order, extract them (or
their keys) into an array then sort them yourself. E.g.:

string[string] myAA;
auto keys = myAA.keys;
sort(keys);
foreach (k; keys) {
... // now keys will be in the expected order
}


T

-- 
Freedom of speech: the whole world has no right *not* to hear my spouting off!


unordered output of an associated array of associated arrays

2022-01-24 Thread forkit via Digitalmars-d-learn
so I'm trying to understand why the output of the code below, is 
in reverse order of the declaration (and how to fix it so that it 
outputs in an ordered way)


i.e. output is:
typeA:
A2:A2value
A1:A1value
typeB:
B3:B3value
B2:B2value
B1:B1value

// --

module test;

import std;

void main()
{
string[string][string] aaTable =
 ([ "typeA" : ["A1" : "A1value", "A2" : "A2value"],
"typeB" : ["B1" : "B1value", "B2" : "B2value", "B3" : 
"B3value"]

 ]);


foreach (topLevelKey, topLevelValue; aaTable.byPair)
{
writefln("%s:", topLevelKey);

foreach(key, value; topLevelValue)
{
writefln("\t%s:%s", key, value);
}
}

}

//--



Re: How to do same as 'nmap' command from within a D program?

2022-01-24 Thread Adam D Ruppe via Digitalmars-d-learn
On Saturday, 22 January 2022 at 20:55:38 UTC, Daren Scot Wilson 
wrote:
I'm writing a command line program to control certain hardware 
devices. I can hardcode or have in a config file the IP 
addresses for the devices, if I know that info. If I don't?


Depending on the hardware, you might be able to send a broadcast 
packet and listen to replies too.


The nmap command you do just does pings to each address in that 
range (btw I actually wrote a little module to turn one of those 
ranges into a bunch of ip address strings: 
https://github.com/adamdruppe/arsd/blob/master/cidr.d ). The 
stdlib doesn't have a convenient ping function though.


But yah depending on the hardware you might be able to do udp 
broadcasts and such. I had this led tower light thing for a 
client I had to set up and that's what i did there - udp 
broadcast a config packet, get the list of all the mac addresses, 
send config packets to change their ips, and get going.


Re: How to do same as 'nmap' command from within a D program?

2022-01-24 Thread Daren Scot Wilson via Digitalmars-d-learn

On Sunday, 23 January 2022 at 06:30:11 UTC, frame wrote:
On Saturday, 22 January 2022 at 20:55:38 UTC, Daren Scot Wilson 
wrote:


I don't see any D std.* libraries that do this. Are there a 
Dub packages I should look at?


If you really want to this in D without any external app or OS 
API you could just ping all possible hosts, see which respond 
and then use `getHostByAddr()` to find the hostname.


Another more professional way is to query the ARP protocol, 
where you send a packet as broadcast to all interfaces in the 
network to find a MAC for a given IP - if any host responses 
with a MAC, the host is up.


You have to build the packet data for yourself, there are 
examples on the web. The socket to use is family:INET, type:RAW 
and protocol:ICMP for ping or RAW for ARP or anything that 
isn't listed in D.


As you can see, it's required to test every possible IP out 
(except for any other discovery protocols supported by your 
network/router). For this reason, any OS does this scan 
periodically and caches the result. On UNIX you can just 
directly read the file `/proc/net/arp`, no need to use nmap.




I'll try this. Looks more educational.  This is a personal 
project, a show-off project. Once I'm done with another portion 
of it, I'll get onto this. My program will need to scan only 
once, not even once per run, since I can stash the results in a 
config file, but once whenever the user knows the hardware 
devices have changed.




Re: Linkage question

2022-01-24 Thread Paul Backus via Digitalmars-d-learn

On Monday, 24 January 2022 at 19:41:30 UTC, frame wrote:
It claims that the D calling convention matches C. But it seems 
that the arguments are pushed in order whereas C does it in 
reverse order and the -218697648 value is indeed my 3rd string 
pointer.


Windows has two calling conventions for C functions, `cdecl` and 
`stdcall`. In D, `cdecl` is called `extern (C)` and `stdcall` is 
called `extern (Windows)`. Windows API functions use the 
`stdcall` convention [1], so you need to use `extern (Windows)` 
when calling them from D.


[1] https://docs.microsoft.com/en-us/cpp/cpp/stdcall?view=msvc-170


Re: Linkage question

2022-01-24 Thread frame via Digitalmars-d-learn
On Monday, 24 January 2022 at 18:30:02 UTC, Stanislav Blinov 
wrote:


The difference is in how arguments are being passed, which you 
seem to have discovered already :)



Would like to know where the linkage format is defined, thx.


It should be here: https://dlang.org/spec/abi.html although 
IIRC it might not be 100% up to date.


Ah, yes. Thanks. Maybe I should read it more carefully =)

It claims that the D calling convention matches C. But it seems 
that the arguments are pushed in order whereas C does it in 
reverse order and the -218697648 value is indeed my 3rd string 
pointer.





Re: Linkage question

2022-01-24 Thread Stanislav Blinov via Digitalmars-d-learn

On Monday, 24 January 2022 at 17:23:01 UTC, frame wrote:

I understand that the linkage must match but besides the name 
mangling, what's happen here? What is the difference if I 
remove the `extern (C)` part from the T alias?


The difference is in how arguments are being passed, which you 
seem to have discovered already :)



Would like to know where the linkage format is defined, thx.


It should be here: https://dlang.org/spec/abi.html although IIRC 
it might not be 100% up to date.


Linkage question

2022-01-24 Thread frame via Digitalmars-d-learn
If I declare a function as extern(C) inside a DLL, I have also to 
cast the function pointer as extern(C) or it fails calling, eg.


```d
// --- my.dll
export extern (C) void log(int mode, string a, string b, string 
c) {

  /* stuff */
}

// --- main.d
alias T = extern (C) void function(int, string, string, string);
auto fnPtr = cast(T)GetProcAddress(/* stuff */);
```

I understand that the linkage must match but besides the name 
mangling, what's happen here? What is the difference if I remove 
the `extern (C)` part from the T alias?


Doing that supplies 2nd and 3rd paramter as fine pointers but the 
1st argument comes wrong (eg. 10 becomes -218697648) and the last 
argument is garbage too, so the D-linkage format is something 
different.


Would like to know where the linkage format is defined, thx.


Re: dustmite and Windows file access errors

2022-01-24 Thread Vladimir Panteleev via Digitalmars-d-learn

On Monday, 24 January 2022 at 17:17:28 UTC, Anonymouse wrote:

Indexing is off for the parent directory. What else can I do?


Disable anti-virus.

If that doesn't help, you could try using Sysinternals Process 
Monitor to check what is accessing the file.




dustmite and Windows file access errors

2022-01-24 Thread Anonymouse via Digitalmars-d-learn
This is maybe more a Windows (11) question than it is a dustmite 
one. Semi-OT.


I'm trying to reduce 
https://forum.dlang.org/thread/muehtdyjabmjxosmj...@forum.dlang.org, and it's Windows so I don't know what I'm doing. After multiple attempts at piecing together a batch tester script that both checks for compiler stderr/stdout *and* the errorlevel of the process, I resigned and wrote a quick thing in D to do it instead.


Off the top of my head;

```d
import std;

static immutable command = `ldc2.exe -flags and stuff copy/pasted 
from dub build -v output`

.replace('\\', '/')
.split(' ');

int main()
{
immutable result = execute(command);
return ((result.code == 5) && !result.output.length) ? 0 : 1;
}
```

Once compiled it seems to work when called manually, and dustmite 
accepts it as a tester, but there are a lot of errors output to 
the console during actual reduction.


Error while attempting to delete init.lookahead.3203: 
init.lookahead.3203\source\somefile.d: The process cannot 
access the file because it is being used by another process.
Error while attempting to rename init.reduced.inprogress to 
init.reduced: Attempting to rename file init.reduced.inprogress 
to init.reduced: Access is denied.


They occur *constantly*, and dustmite halts and waits a full 
second each time before retrying, sometimes with the same message 
repeated some 5 times. (Meaning access to the file was blocked 
for the same 5 seconds.)


Indexing is off for the parent directory. What else can I do?