Re: Can not get struct member addresses at compile time

2021-06-16 Thread Ali Çehreli via Digitalmars-d-learn

On 6/16/21 3:27 PM, Doeme wrote:

On Wednesday, 16 June 2021 at 22:16:54 UTC, H. S. Teoh wrote:
The compiler does not (and cannot) know.  But the runtime dynamic 
linker can, and does.  The two are bridged by the compiler emitting a 
relocatable symbol for the address of the global variable, with a 
table of relocations (offsets in the code) that the runtime linker 
patches the actual addresses into when the program is executed.



T


Exactly! Except that the dynamic linker is not really involved here, 
since all the symbols can/must be relocated statically at link time.


Thank you, both. It still rules out an address at "compile time" in 
general. For example, we cannot use such an address when instantiating a 
template, or static array length, etc.


And if I understand it correctly, there must be a pointer *variable* for 
the linker to initialize. Fine then: That's how this usage works for C 
but not for D. :)


Thank you,
Ali



Re: Struct assignment fails, why?

2021-06-16 Thread Brian via Digitalmars-d-learn

On Wednesday, 16 June 2021 at 20:54:07 UTC, H. S. Teoh wrote:
On Wed, Jun 16, 2021 at 08:44:46PM +, Brian via 
Digitalmars-d-learn wrote: [...]

struct item
{
string name;
int type;
};

[...]

new_item = { "item1", 1 };


The {...} initializer syntax is only available in variable 
declarations, e.g.:


item i = { "item1", 1 };

You cannot use this syntax in assignment statements.

A simple alternative is to use constructor syntax for 
constructing an instance of the struct:


new_item = item("item", 1);


T


Gotcha. Thanks.

~Brian


Re: Can not get struct member addresses at compile time

2021-06-16 Thread Doeme via Digitalmars-d-learn

On Wednesday, 16 June 2021 at 22:16:54 UTC, H. S. Teoh wrote:
The compiler does not (and cannot) know.  But the runtime 
dynamic linker can, and does.  The two are bridged by the 
compiler emitting a relocatable symbol for the address of the 
global variable, with a table of relocations (offsets in the 
code) that the runtime linker patches the actual addresses into 
when the program is executed.



T


Exactly! Except that the dynamic linker is not really involved 
here, since all the symbols can/must be relocated statically at 
link time.


Re: Can not get struct member addresses at compile time

2021-06-16 Thread H. S. Teoh via Digitalmars-d-learn
On Wed, Jun 16, 2021 at 02:42:41PM -0700, Ali Çehreli via Digitalmars-d-learn 
wrote:
[...]
> Actually, it is news to me that the compiler can know (determine?) the
> address of a global variable.
[...]

The compiler does not (and cannot) know.  But the runtime dynamic linker
can, and does.  The two are bridged by the compiler emitting a
relocatable symbol for the address of the global variable, with a table
of relocations (offsets in the code) that the runtime linker patches the
actual addresses into when the program is executed.


T

-- 
War doesn't prove who's right, just who's left. -- BSD Games' Fortune


Re: Can not get struct member addresses at compile time

2021-06-16 Thread Doeme via Digitalmars-d-learn

On Wednesday, 16 June 2021 at 21:42:41 UTC, Ali Çehreli wrote:

On 6/16/21 8:47 AM, Doeme wrote:

> On Wednesday, 16 June 2021 at 13:36:07 UTC, Ali Çehreli wrote:
>> On 6/16/21 2:27 AM, Doeme wrote:
>>
>> > How does one get the address of a struct member?
>>
>> Here is an experiment with offsetof and opDispatch:
>
> Cool stuff!
> I actually tried a very similar approach once, but it did not
work out,
> since the D compilers refuse to do pointer arithmetic at
compile time :/
>
> ```d
> struct Foo{
>   ubyte bar;
> }
>
> void* membaddr(void *ptr, ulong offset){
>  return ptr+offset;
> }
>
> __gshared Foo foo;
> void* bar = membaddr(, foo.bar.offsetof);
> //Error: cannot perform arithmetic on `void*` pointers at
compile time
> ```
>
> I guess that the opDispatch-method will suffer from the same
issue...

No, opDispatch does not work either for compile time addresses.

Actually, it is news to me that the compiler can know 
(determine?) the address of a global variable. I thought the 
loador would determine the addresses, but apparently not. Is it 
really a constant compiled value in the case of C? Can you show 
an example please?


Ali


The compiler can, in deed, not know the address, but the linker 
can.


Example:

```c
#include 

struct Foo{
int bar;
int baz;
};

struct Foo foo;
static const void *fooptr = 
static const void *barptr = 
static const void *bazptr = 

int main(int argc, char **argv){
	printf("Address of foo: %p\n", fooptr); //Address of foo: 
0x55fbd8292030
	printf("Address of bar: %p\n", barptr); //Address of bar: 
0x55fbd8292030
	printf("Address of bau: %p\n", bazptr); //Address of bau: 
0x55fbd8292034

return 0;
}

```

We can see that the code actually outputs the right addresses.

If we investigate the object file passed down to the linker, we 
see:


```
$ gcc -c test.c
$ objdump -x test.o

[...]

SYMBOL TABLE:
 ldf *ABS*   test.c
 ld  .text   .text
 ld  .data.rel.local	 
.data.rel.local

 l O .data.rel.local0008 fooptr
0008 l O .data.rel.local0008 barptr
0010 l O .data.rel.local0008 bazptr
 ld  .rodata .rodata
 g O .bss   0008 foo
 g F .text  0070 main
 *UND*	 
_GLOBAL_OFFSET_TABLE_

 *UND*   printf

[...]

RELOCATION RECORDS FOR [.data.rel.local]:
OFFSET   TYPE  VALUE
 R_X86_64_64   foo
0008 R_X86_64_64   foo
0010 R_X86_64_64   foo+0x0004

[...]
```

This tells us that:
* There are 3 variables in the initialized .data.rel.local 
section, our pointers.
* There is one variable in the zeroed .bss section, our instance 
of struct Foo
* To the positions of the of our three pointers in the 
.data.rel.local section, there is being written the address of 
the symbol foo, foo, and lastly, foo+4.


Thus, the address is only known at link time, but it _can_ be 
known by placing the right relocation commands to the object 
elf-file (i.e. relocation + offset, foo+4).




Re: Can not get struct member addresses at compile time

2021-06-16 Thread Ali Çehreli via Digitalmars-d-learn

On 6/16/21 8:47 AM, Doeme wrote:

> On Wednesday, 16 June 2021 at 13:36:07 UTC, Ali Çehreli wrote:
>> On 6/16/21 2:27 AM, Doeme wrote:
>>
>> > How does one get the address of a struct member?
>>
>> Here is an experiment with offsetof and opDispatch:
>
> Cool stuff!
> I actually tried a very similar approach once, but it did not work out,
> since the D compilers refuse to do pointer arithmetic at compile time :/
>
> ```d
> struct Foo{
>   ubyte bar;
> }
>
> void* membaddr(void *ptr, ulong offset){
>  return ptr+offset;
> }
>
> __gshared Foo foo;
> void* bar = membaddr(, foo.bar.offsetof);
> //Error: cannot perform arithmetic on `void*` pointers at compile time
> ```
>
> I guess that the opDispatch-method will suffer from the same issue...

No, opDispatch does not work either for compile time addresses.

Actually, it is news to me that the compiler can know (determine?) the 
address of a global variable. I thought the loador would determine the 
addresses, but apparently not. Is it really a constant compiled value in 
the case of C? Can you show an example please?


Ali




Re: Struct assignment fails, why?

2021-06-16 Thread H. S. Teoh via Digitalmars-d-learn
On Wed, Jun 16, 2021 at 08:44:46PM +, Brian via Digitalmars-d-learn wrote:
[...]
> struct item
> {
> string name;
> int type;
> };
[...]
> new_item = { "item1", 1 };

The {...} initializer syntax is only available in variable declarations,
e.g.:

item i = { "item1", 1 };

You cannot use this syntax in assignment statements.

A simple alternative is to use constructor syntax for constructing an
instance of the struct:

new_item = item("item", 1);


T

-- 
Everybody talks about it, but nobody does anything about it!  -- Mark Twain


Re: Internal Server Error on reload of dfeed.js

2021-06-16 Thread Vladimir Panteleev via Digitalmars-d-learn

On Wednesday, 16 June 2021 at 06:28:40 UTC, guest wrote:

STR:

1. open 
http://forum.dlang.org/static-bundle/637528586548394375/dlang.org/js/dlang.js+js/dfeed.js

2. press reload (F5 or ctrl+R)


Noticed this too and fixed it a bit ago. It was sending 500 
instead of 304, so actually the only way you could see it was to 
press F5 (but not Ctrl+F5).


Struct assignment fails, why?

2021-06-16 Thread Brian via Digitalmars-d-learn

Hello all --

I have a question about assigning to structs.

I want to be able to create an array of structs that may contain 
different contents depending on user input. I have reduced the 
test case down.


The following fails to compile:

```d
import std.stdio;

struct item
{
string name;
int type;
};

item[] items;

void main(string[] args)
{
item new_item;

for (int i = 0; i < args.length; i++) {
if (args[i] == "item1") {
new_item = { "item1", 1 };
} else if (args[i] == "item2") {
new_item = { "item2", 2 };
} else {
new_item = { "item3", 3 };
}

items ~= new_item;
}

for (int i = 0; i < items.length; i++)
writeln(items[i].name);
}
```

This fails (dmd 2.097) with the following:
```d
struct_bad.d(17): Error: found `}` when expecting `;` following 
statement
struct_bad.d(17): Deprecation: use `{ }` for an empty statement, 
not `;`
struct_bad.d(18): Error: found `else` when expecting `;` 
following statement
struct_bad.d(19): Error: found `}` when expecting `;` following 
statement
struct_bad.d(19): Deprecation: use `{ }` for an empty statement, 
not `;`
struct_bad.d(20): Error: found `else` when expecting `;` 
following statement
struct_bad.d(21): Error: found `}` when expecting `;` following 
statement
struct_bad.d(21): Deprecation: use `{ }` for an empty statement, 
not `;`
struct_bad.d(24): Error: found `items` when expecting `;` 
following statement

struct_bad.d(24): Error: found `~=` instead of statement
struct_bad.d(30): Error: found `End of File` when expecting `}` 
following compound statement
struct_bad.d(30): Error: found `End of File` when expecting `}` 
following compound statement
struct_bad.d(30): Error: found `End of File` when expecting `}` 
following compound statement

```

However, a slight tweak allows the code to compile and work 
correctly.

```d
import std.stdio;

struct item
{
string name;
int type;
};

item[] items;

void main(string[] args)
{
for (int i = 0; i < args.length; i++) {
if (args[i] == "item1") {
item new_item = { "item1", 1 };
items ~= new_item;
} else if (args[i] == "item2") {
item new_item = { "item2", 2 };
items ~= new_item;
} else {
item new_item = { "item3", 3 };
items ~= new_item;
}
}

for (int i = 0; i < items.length; i++)
writeln(items[i].name);
}
```

I guess I am unclear as to why the first fails and the second 
succeeds.


TIA.

~Brian


Re: How to translate this C macro to D mixin/template mixin?

2021-06-16 Thread Tejas via Digitalmars-d-learn

On Wednesday, 16 June 2021 at 05:48:21 UTC, VitaliiY wrote:

On Tuesday, 15 June 2021 at 12:39:40 UTC, Dennis wrote:

On Tuesday, 15 June 2021 at 12:18:26 UTC, VitaliiY wrote:

[...]
```D

enum string ADDBITS(string a, string b) = `
{
bitbuffer = (bitbuffer<<(`~a~`))|((`~b~`)&((1<<`~a~`)-1));
numbits += (`~a~`);
mixin(STOREBITS);
}`;

// on use: ADDBITS(varA, varB) becomes
mixin(ADDBITS!("varA", "varB"));
`

[...]


Thank you, Dennis. I tried with this kind of mixin, but a, b - 
are type of 'int so it's confusing to use them as mixin 
arguments.



Use the 
[.stringof](https://dlang.org/spec/property.html#stringofhttps://dlang.org/spec/property.html#stringof) property. That should do it.





Re: What is this undefined reference with -betterC about?

2021-06-16 Thread jfondren via Digitalmars-d-learn

On Wednesday, 16 June 2021 at 16:27:13 UTC, Dennis wrote:

On Wednesday, 16 June 2021 at 14:38:10 UTC, jfondren wrote:

What do I change to
1. a script like this that uses hostname
2. the hostname module

so that both can be built with -betterC when and only when
the script is using -betterC?


That's currently the situation: you can only build when both 
are betterC or else you get a linker error. It has to be a 
linker error, dmd cannot know at the time of compiling project 
A how project B is going to be compiled and vice versa.


It's dub that's calling dmd though. Cargo handles this situation 
with
features: https://doc.rust-lang.org/cargo/reference/features.html 
Where

this case would look something like

```
[dependencies]
hostname = { version = "0.1.1", features = ["betterC"] }
```

in the script's dub config that uses hostname.

I feel like I've seen similar configurations in dub configs, but 
I see

nothing about this in the documentation.


It noticed your code looks like this:
```D
version(D_BetterC) {
char* hostnamez;
} else {
immutable char* hostnamez;
}
```

The different types result in different mangles, causing the 
linking errors. Why not simply give them the same type?


the pragma(crt_constructor) function can't initialize immutables:
https://forum.dlang.org/post/wvjfygxfvmoaortmn...@forum.dlang.org


Re: What is this undefined reference with -betterC about?

2021-06-16 Thread Dennis via Digitalmars-d-learn

On Wednesday, 16 June 2021 at 16:27:13 UTC, Dennis wrote:
It has to be a linker error, dmd cannot know at the time of 
compiling project A how project B is going to be compiled and 
vice versa.


Well I suppose you could use a specific dub configuration, maybe 
giving 'hostname' a targetType "sourceLibrary" or something, but 
I would just make the abi consistent.


Re: What is this undefined reference with -betterC about?

2021-06-16 Thread Dennis via Digitalmars-d-learn

On Wednesday, 16 June 2021 at 14:38:10 UTC, jfondren wrote:

What do I change to
1. a script like this that uses hostname
2. the hostname module

so that both can be built with -betterC when and only when
the script is using -betterC?


That's currently the situation: you can only build when both are 
betterC or else you get a linker error. It has to be a linker 
error, dmd cannot know at the time of compiling project A how 
project B is going to be compiled and vice versa.


It noticed your code looks like this:
```D
version(D_BetterC) {
char* hostnamez;
} else {
immutable char* hostnamez;
}
```

The different types result in different mangles, causing the 
linking errors. Why not simply give them the same type?


Re: Can not get struct member addresses at compile time

2021-06-16 Thread Doeme via Digitalmars-d-learn

On Wednesday, 16 June 2021 at 11:56:31 UTC, Mike Parker wrote:

https://dlang.org/spec/pragma.html#crtctor


Very interesting, thanks for the hint! This is definitely a 
viable solution, though if there's a way to let the linker 
determine the pointer address, that'd be even better.


In C, it's a comparatively standard thing to do:

```c
struct Foo{
char bar;
};

struct Foo foo;
void *ptr =  //compiles, links and works
```

Why the D compilers would not pass this down to the linker eludes 
me.





Re: Can not get struct member addresses at compile time

2021-06-16 Thread Doeme via Digitalmars-d-learn

On Wednesday, 16 June 2021 at 13:36:07 UTC, Ali Çehreli wrote:

On 6/16/21 2:27 AM, Doeme wrote:

> How does one get the address of a struct member?

Here is an experiment with offsetof and opDispatch:


Cool stuff!
I actually tried a very similar approach once, but it did not 
work out, since the D compilers refuse to do pointer arithmetic 
at compile time :/


```d
struct Foo{
 ubyte bar;
}

void* membaddr(void *ptr, ulong offset){
return ptr+offset;
}

__gshared Foo foo;
void* bar = membaddr(, foo.bar.offsetof);
//Error: cannot perform arithmetic on `void*` pointers at compile 
time

```

I guess that the opDispatch-method will suffer from the same 
issue...


Re: What is this undefined reference with -betterC about?

2021-06-16 Thread jfondren via Digitalmars-d-learn

On Wednesday, 16 June 2021 at 14:21:40 UTC, jfondren wrote:


Why isn't this linking?


OK, with verbose commands I see that libhostname.a is built 
without -betterC


So that's why this fails to link.

What do I change to
1. a script like this that uses hostname
2. the hostname module

so that both can be built with -betterC when and only when
the script is using -betterC?


Re: Can not get struct member addresses at compile time

2021-06-16 Thread Mike Parker via Digitalmars-d-learn

On Wednesday, 16 June 2021 at 13:26:43 UTC, jfondren wrote:



Is this a bug?


Probably. Please file an issue if there isn't one already:

https://issues.dlang.org/




What is this undefined reference with -betterC about?

2021-06-16 Thread jfondren via Digitalmars-d-learn

Here's a complete script that you can run right now, using
a dub module that I just updated:

```d
#!/usr/bin/env dub
/+ dub.sdl:
dependency "hostname" version="~>0.1.1"
buildOptions "betterC"
+/

extern(C) void main() {
import hostname : hostnamez;
import core.stdc.stdio : printf;

printf("hostname: %s", hostnamez);
}
```

... which fails:

```
/usr/bin/ld: 
/tmp/.dub/build/hostnameex2-~master/application-debug-linux.posix-x86_64-dmd_v2.097.0-96F370DD71342805A23ECDFD2C6CCE6C/hostnameex2.o: in function `main':
/home/jfondren/mars/learn/./hostnameex2.d:11: undefined reference 
to `_D8hostname9hostnamezPa'

```

I've rm -rf'd /tmp/.dub and ~/.dub/packages , I've gotten things 
to a point
where I could modify dub's cached hostname/source.d and confirm 
that e.g.
pragma(msg, hostnamez.mangleof) has exactly the same output in 
that file
as in the script above. This all works fine if instead of a dub 
dependency

I add the path to hostname.d in dflags.

And this script works fine, without betterC:

```d
#!/usr/bin/env dub
/+ dub.sdl:
dependency "hostname" version="~>0.1.1"
+/

void main() {
import std.stdio : writeln;
import hostname : hostname, hostnamez;
import std.string : fromStringz;

writeln("hostname: ", hostname);
writeln("hostname: ", hostnamez.fromStringz);
}
```

Why isn't this linking?


Re: Can not get struct member addresses at compile time

2021-06-16 Thread Ali Çehreli via Digitalmars-d-learn

On 6/16/21 2:27 AM, Doeme wrote:

> How does one get the address of a struct member?

Here is an experiment with offsetof and opDispatch:

struct Foo{
 ubyte bar;
 int i;
}

auto addrOf(T)(ref T t) {
  static struct AddrOf {
void * origin;
auto opDispatch(string member)() {
  return origin + mixin ("T." ~ member ~ ".offsetof");
}
  }
  return AddrOf();
}

import std.stdio;

__gshared Foo foo;

void main() {
  writeln();

  writeln(foo.addrOf.bar);
  writeln(foo.addrOf.i);

  // Alternative syntax
  writeln(addrOf(foo).bar);
  writeln(addrOf(foo).i);
}

Ali



Re: Can not get struct member addresses at compile time

2021-06-16 Thread jfondren via Digitalmars-d-learn

On Wednesday, 16 June 2021 at 11:56:31 UTC, Mike Parker wrote:

https://dlang.org/spec/pragma.html#crtctor

"as a simple replacement for shared static this in betterC mode"

Cool.

However,

```d
immutable int example;

version(D_BetterC) {
pragma(crt_constructor) extern(C) void initialize() {
example = 1;
}
} else {
shared static this() {
example = 1;
}
}
```

this compiles without -betterC; with -betterC it errors out:

Error: cannot modify `immutable` expression `example`

Is this a bug?


Re: Can not get struct member addresses at compile time

2021-06-16 Thread Mike Parker via Digitalmars-d-learn

On Wednesday, 16 June 2021 at 09:27:25 UTC, Doeme wrote:

Is there an alternative to get to this point? Static module 
initializers are not really an option, since the whole thing 
should be -betterC.




```D
import core.stdc.stdio;
struct Foo{
 ubyte bar;
}

__gshared Foo foo;
void* baz = 
void* bar;

extern(C):

pragma(crt_constructor)
void initialize() { bar =  }

void main()
{
*(cast(ubyte*)bar) = 10;
printf("%d", foo.bar);
}
```

https://dlang.org/spec/pragma.html#crtctor



Can not get struct member addresses at compile time

2021-06-16 Thread Doeme via Digitalmars-d-learn

Hi!

I'm currently investigating why I can not take the address of a 
static struct-element at compile time (afaik the linker should be 
able to resolve this, and doing the identical thing in C works...)


```d
struct Foo{
 ubyte bar;
}

__gshared Foo foo;
void* baz = \   //works
void* bar = \   //Error: static variable `foo` cannot be 
read at compile time

```

Does this have to do with ".bar" potentially being a function 
call?

How does one get the address of a struct member?

The higher level problem of this question is that I want to make 
a pointer-map of a struct:


```d
import std.meta;
struct Foo{
ubyte a;
ushort b;
}

template ptrize(alias S){
enum ptrize =  \
}

__gshared Foo f;
static immutable void*[] map = [staticMap!(ptrize, f.tupleof)];
```

Is there an alternative to get to this point? Static module 
initializers are not really an option, since the whole thing 
should be -betterC.


Thanks for any hints!


Re: Parallel For

2021-06-16 Thread jfondren via Digitalmars-d-learn

On Wednesday, 16 June 2021 at 06:29:21 UTC, z wrote:

On Tuesday, 15 June 2021 at 06:39:24 UTC, seany wrote:

...


This is the best I could do: https://run.dlang.io/is/dm8LBP
For some reason, LDC refuses to vectorize or even just unroll 
the nonparallel version, and more than one `parallel` corrupts 
the results.


The same trick as before is useful here: insert a write(i+ii);
before the assignment and see if the output looks reasonable.

Instead of only unique indices, there are many repeats, as of
course (i=0)+(ii=1) == (i=1)+(ii=0)

```d
import std;

void main() {
int[] a = [1, 2, 3, 4, 5, 6, 7, 8, 9];
int[] b = [11, 12, 13, 14, 15, 16, 17, 18];
int[] c = new int[a.length * b.length];
foreach (i, aa; parallel(a)) {
foreach (ii, bb; parallel(b)) {
c[i * b.length + ii] = aa + bb;
}
}
writeln(c);
}
```


Re: What exactly gets returned with extern(C) export string func() ?

2021-06-16 Thread frame via Digitalmars-d-learn

On Wednesday, 16 June 2021 at 02:46:36 UTC, cc wrote:

I can't seem to get it to work as a return type, but 
interestingly it does work as an out/pass by ref parameter.


Probably for returning the struct it needs some allocation 
directive in C# but I'm not sure. Maybe C# also tries something 
to do with the IntPtr. It may work if you use a struct on the DLL 
side too and convert any specific things like pointers to simple 
integers instead.


The out keyword however basically is just a pointer to the 
struct, so reading directly from the memory offset from the DLL 
works instead.


As long the GC sees the data alive - .(i)dup doesn't protect your 
memory here. The data could be collected by the GC anytime the 
function call goes out of scope.


Re: LNK2019 error in the C++ interface

2021-06-16 Thread dokutoku via Digitalmars-d-learn

On Thursday, 10 June 2021 at 15:19:27 UTC, kinke wrote:

Confirmed: https://issues.dlang.org/show_bug.cgi?id=22014


Thank you for the bug report. I'm glad I couldn't handle it 
myself.


The only thing that bothers me is that there is no sign of this 
problem being fixed.

I fear that this may be the case forever.

On Thursday, 10 June 2021 at 15:19:27 UTC, kinke wrote:
Wrt. `tagRECT`, this should come in handy (for a druntime fix): 
https://dlang.org/changelog/2.097.0.html#pragma-mangle-aggregate


I don't see how this helps with the modifications related to 
tagRECT.




Internal Server Error on reload of dfeed.js

2021-06-16 Thread guest via Digitalmars-d-learn

STR:

1. open 
http://forum.dlang.org/static-bundle/637528586548394375/dlang.org/js/dlang.js+js/dfeed.js

2. press reload (F5 or ctrl+R)


Re: Parallel For

2021-06-16 Thread z via Digitalmars-d-learn

On Tuesday, 15 June 2021 at 06:39:24 UTC, seany wrote:

...


This is the best I could do: https://run.dlang.io/is/dm8LBP
For some reason, LDC refuses to vectorize or even just unroll the 
nonparallel version, and more than one `parallel` corrupts the 
results.
But judging by the results you expected and what you described, 
you could maybe replace it by a ton of `c[] = a[] *operand* b[]` 
operations?
Unless you use conditionals after or do something else that 
confuses the compiler, it will maybe use SSE/AVX instructions, 
and at worst use basic loop unrolling.