std.math log and family

2018-10-30 Thread Joe via Digitalmars-d-learn
I've discovered that the 'log' function as well several similar 
functions are only defined as taking a real argument and 
returning a real, unlike most other std.math functions, which 
have triple definitions (also supporting double and float types). 
This created a problem when I tried compiling code like the 
following:


---
import std.math;

alias double function(double) Funcptr;

Funcptr sinptr = 
Funcptr tanptr = 
Funcptr logptr = 
---

dmd (and ldc2) report

test.d(7): Error: cannot implicitly convert expression & log of 
type real function(real x) pure nothrow @nogc @safe to double 
function(double)


[ldc2 also reports
test.d(6): Error: cannot implicitly convert expression & tan of 
type real function(real x) pure nothrow @nogc @trusted to double 
function(double)

but apparently this is an LDC-only problem]

I'd like to know if the lack of double/float versions of 'log', 
'log10', etc. are intentional, i.e., there's some rationale 
behind it, or an oversight.  I'd also like to know the 
proper/best way to deal with the error, considering the real code 
embeds the 'Funcptr's in an array of structs.  Is it better to 
write a function 'mylog' that internally casts the argument and 
the return value, or is there some safe way to cast away the 
'log' function at the point of initializing the array?


Also, is it preferable to post the first question 
(intentional/oversight) in the Phobos forum? And what is the 
preferred way of reporting the LDC problem, via GitHub?


Re: Dlang tour - Unittesting example

2018-10-02 Thread Joe via Digitalmars-d-learn

On Tuesday, 2 October 2018 at 13:24:09 UTC, Basile B. wrote:

The problem is the NaN madness.
Since several values are NaN there's this strange stuff:

void main()
{
import std.stdio;
import std.math : isNaN;
double d;

writeln(d.init);// nan
writeln(d); // nan
writeln(d.nan); // nan

assert(d.isNaN);
assert(d == d.nan);  // fails
assert(d == d.init); // fails
}

the last assert is just crazy.


OK, so changing the example from

// .init a special built-in property that
// returns the initial value of type.
assert(vec.x == double.init);

to

import std.math : isNaN;
assert(vec.x.isNaN);

doesn't cause the crash. Although I'm a bit puzzled still, I 
thought (coming from Python) that when you ran the unittest 
version it would report which tests passed and which failed, not 
run through main().


Re: Dlang tour - Unittesting example

2018-10-02 Thread Joe via Digitalmars-d-learn

On Tuesday, 2 October 2018 at 12:25:19 UTC, Joe wrote:

On Tuesday, 2 October 2018 at 09:59:28 UTC, bauss wrote:

On Tuesday, 2 October 2018 at 04:13:01 UTC, Joe wrote:

There appears to be a problem with the example at

https://tour.dlang.org/tour/en/gems/unittesting

If compiled with -unittest, the resulting program crashes. It 
happens with ldc2 on Linux but it can also be seen if you 
click on "Export" and run it with dmd -unittest.


I think it's more likely a problem with your OS.

I am unable to reproduce that with either of dmd or ldc.


Well then it's also a problem with run.dlang.io, since as I 
said it also happens when you run it there.


I forgot to mention: at the end, it reports "1/1 unittests 
FAILED". I see three tests--two in the struct and the separate 
one--but the assertion failure is in line 49 (the standalone) so 
apparently the other two are not being run (or reported).


Re: Dlang tour - Unittesting example

2018-10-02 Thread Joe via Digitalmars-d-learn

On Tuesday, 2 October 2018 at 09:59:28 UTC, bauss wrote:

On Tuesday, 2 October 2018 at 04:13:01 UTC, Joe wrote:

There appears to be a problem with the example at

https://tour.dlang.org/tour/en/gems/unittesting

If compiled with -unittest, the resulting program crashes. It 
happens with ldc2 on Linux but it can also be seen if you 
click on "Export" and run it with dmd -unittest.


I think it's more likely a problem with your OS.

I am unable to reproduce that with either of dmd or ldc.


Well then it's also a problem with run.dlang.io, since as I said 
it also happens when you run it there.


Dlang tour - Unittesting example

2018-10-01 Thread Joe via Digitalmars-d-learn

There appears to be a problem with the example at

https://tour.dlang.org/tour/en/gems/unittesting

If compiled with -unittest, the resulting program crashes. It 
happens with ldc2 on Linux but it can also be seen if you click 
on "Export" and run it with dmd -unittest.


Re: Access to structures defined in C

2018-09-18 Thread Joe via Digitalmars-d-learn

On Tuesday, 18 September 2018 at 13:47:50 UTC, Atila Neves wrote:

On Tuesday, 18 September 2018 at 02:39:39 UTC, Joe wrote:
The second type is like that shown above. The first is a 
simpler array of pointers to int, e.g.,


int *yp = {2, 4, 0};
int *yq = {10, 12, 0};


This is valid C in the sense that it compiles, but I doubt it 
does what you think it does. This is equivalent code:


int *yp = 2;
int *yq = 10;


Sorry, Atila, I got confused looking at my two cases. I should 
have said "an array of ints", e.g.,


int yp[] = {2, 4, 0};
int yq[] = {10, 12, 0};


int *ys[] = {yp, yq, 0};


This isn't even valid C code.


It is, because C treats 'yp' as a pointer.


In D, I first declared these as

int[] yp = [2, 4];
int[] yq = [10, 12];
__gshared int*[] ys = [ ,  ];


D dynamic arrays are not equivalent to C arrays.

It's hard to see what you're trying to do with the code you 
posted. Have you tried instead to use a tool to translate the C 
headers?


At this point, I've translated everything, even the code above. I 
had to use 'immutable(int [])' in the second and higher level 
arrays like 'ys' so that they could refer to 'yp' and 'yq' 
(without the address operators).


I still have to make several changes to the library code because 
these arrays were declared as dynamic arrays of pointers, of size 
1, to bypass bounds checking. Now they're proper dynamic arrays, 
and I can use foreach on them and get other D benefits.


However, I still would like to have a deeper understanding of the 
"static variable yp cannot be read at compile time" error 
messages which went away when I declared yp immutable.


Re: Access to structures defined in C

2018-09-17 Thread Joe via Digitalmars-d-learn

On Sunday, 10 June 2018 at 17:59:12 UTC, Joe wrote:
That worked but now I have a more convoluted case: a C array of 
pointers to int pointers, e.g.,


int **xs[] = {x1, x2, 0};
int *x1[] = {x1a, 0};
int *x2[] = {x2a, x2b, 0};
...
int x2a[] = { 1, 3, 5, 0};

Only the first line is exposed (and without the 
initialization). So I tried:


extern(C) __gshared extern int**[1] xs;


After a long hiatus, I'm back to working on something related to 
the above, but now that various other C pieces have been 
converted to D I'm down to converting these static arrays to D. 
There are two arrays that are giving me trouble. The second type 
is like that shown above. The first is a simpler array of 
pointers to int, e.g.,


int *yp = {2, 4, 0};
int *yq = {10, 12, 0};
int *ys[] = {yp, yq, 0};

In D, I first declared these as

int[] yp = [2, 4];
int[] yq = [10, 12];
__gshared int*[] ys = [ ,  ];

The compiler (ldc2) gave errors like "cannot take address of 
thread-local variable yp at compile time" or "static variable yp 
cannot be read at compile time" (when I replaced the "" by 
"yp[0]". Eventually, I managed to get them to compile without 
errors by using the following:


immutable int[] yp = [2, 4];
immutable int[] yq = [10, 12];
__gshared immutable(int[])[] ys = [ yp, yq ];

I still haven't tested them (or linked them) so I don't know what 
other changes I'll have to make to the library (now in D) where 
ys is declared as:


__gshared extern int*[] ys;

Presumably changing it to

__gshared extern immutable(int[])[] ys;

should do the trick (everything is still within extern (C))? But 
I suspect I'll have to change several array access statements as 
well.


However, I've been unable to compile the other case, which now 
looks like this:


immutable int x1a[] = [ 9, 7, 5];
immutable(int[])[] x1 = [ x1a ];
immutable(int[])[] x2a = [ 1, 3, 5];
...
immutable(int[])[] x2 = [ x2a, x2b ];
__gshared immutable(int[])[][] xs = [ x1, x2 ];

The error is like "static variable x2a cannot be read at compile 
time". It seems like I would have to wrap that immutable(int[]) 
within another immutable, as


immutable(immutable(int[])[]) x2 ...

and extend that to xs as well.

I'll try it later but I'd like some confirmation or better yet, 
pointers to where this is explained in some comprehensible way, 
i.e., on what can you apply an address operator or array 
subscript and when, is the behavior differerent for immutable, 
const, static, thread-local and why?


Re: Linking a C program with D library

2018-08-15 Thread Joe via Digitalmars-d-learn

On Wednesday, 15 August 2018 at 06:39:50 UTC, Mike Parker wrote:
String literals are implicitly convertible to const(char)* and 
are guaranteed to be nul-terminated like a C string, so this 
works:


[...]

Does that help?


Yes, indeed. I think I possibly read about literal strings being 
nul-terminated somewhere but it must've slipped my mind.


Re: Linking a C program with D library

2018-08-14 Thread Joe via Digitalmars-d-learn

On Wednesday, 15 August 2018 at 01:56:34 UTC, Mike Parker wrote:
The correct thing to do is to keep the original C function 
signatures in the converted code, i.e. don't change char* to 
string[]. And don't use anything from Phobos internally that 
requires linking. In other words, treat your converted code as 
C code in a D module as much as possible. Only when the 
conversion is complete and everything is in D do you start 
pulling in the D features.


I understand that, Mike. However if I'm not mistaken given 
something in C like


char* strs[] = { "This", "is a", "test"};

AFAIK, even with -betterC and an extern (C), the literals will 
still be understood by D as type "string", and there is no other 
way around it, right?


I could put the array and the function in its own C file for the 
time being, but instead chose to replace the toStringz by a small 
hack: use memcpy to copy the string to a stack fixed, big enough 
array and a NUL terminator.


Linking a C program with D library

2018-08-14 Thread Joe via Digitalmars-d-learn
I'm attempting a piecemeal conversion of some C programs. I've 
converted a few that depend on C modules that are in a library 
and now I'm sort of in the middle of converting those C modules. 
One of them has an array of strings, i.e., array of char*, which 
most easily translated to D's string[]. However, the array is 
used by a function that expects a const char*, so I had to use 
toStringz to pass those values.


Now there are some C programs that haven't been converted yet, 
but they depend on the function above. When linking those 
programs, the linker complains about an undefined reference to 
the mangled name of std.string.toStringz.


What is the most appropriate way around this? Is there a way to 
declare an array of const char* and initialize it to literal 
strings? Or can the mangled name (and Phobos library) somehow be 
made visible to the linker?


?? How to subscribe to Multicast Broadcasts ??

2018-08-12 Thread Joe via Digitalmars-d-learn

Hello All!

I've been trying every possible combination and cannot get 
anything working. (>_<)


This is I think the closest I've got, I think the problem may be 
with the 3 argument.  I'm not sure how to join the Multicast IP 
membership?

(this code currently does not work - throws error:
'Unable to set socket option: An invalid argument was supplied'.)

Socket listen_socket = new Socket(AddressFamily.INET, 
SocketType.DGRAM, ProtocolType.UDP);
listen_socket.setOption(SocketOptionLevel.IGMP, 
SocketOption.IPV6_JOIN_GROUP, 1);

auto adr = getAddress("0.0.0.0", "56000");
listen_socket.bind(adr[0]);


This is how the messages are sent (which works fine):

Socket udp_broadcast_soc = new UdpSocket();
udp_broadcast_soc.setOption(SocketOptionLevel.SOCKET, 
SocketOption.BROADCAST, 1);

auto adr = getAddress("239.192.0.10", 54000);
udp_broadcast_soc.sendTo(, adr[0]);


Please Please Please Help, I am desperate!

Many Thanks in Advance for your time & attention,
-joe


Re: How to call a C function from D that takes a FILE * as an argument?

2018-07-03 Thread Joe via Digitalmars-d-learn

On Wednesday, 4 July 2018 at 02:16:00 UTC, Seb wrote:

Hmm, calling e.g. fprintf with stdout should just work:

---
void main()
{
import core.stdc.stdio;
fprintf(stdout, "Hello %s", "world".ptr);
}
---

Could you maybe provide your whole code?


This short test program shows the error:

---
import std.stdio;


void main()
{
extern (C) void list(FILE *fd);
list(stdout);
}
---

Now I fixed this by changing the import to core.stdc.stdio. I 
guess the problem is if you import std.stdio (which brings in the 
other one), there are two slightly incompatible stdout's and the 
D takes precedence.


Re: How to call a C function from D that takes a FILE * as an argument?

2018-07-03 Thread Joe via Digitalmars-d-learn

On Wednesday, 4 July 2018 at 01:58:15 UTC, Seb wrote:

So just add the declaration to your D file:

---
extern(C) void myCfunction(FILE* stream);
---


I do have a similar declaration in D.  It appears the problem is 
that the C program I'm trying to convert passes stdout as the 
argument and the D compiler complains somewhat like the following:



Error: function foo.main.myCfunction (shared(_IO_FILE)* stream) 
is not callable using argument types (File)


So I guess the question is what to pass instead of stdout.


How to call a C function from D that takes a FILE * as an argument?

2018-07-03 Thread Joe via Digitalmars-d-learn
The subject basically says it all. The C function uses the 
argument to call fprintf and also passes it to other functions 
where it's used to call fileno, fprintf or putc.


Re: Access to structures defined in C

2018-06-10 Thread Joe via Digitalmars-d-learn

On Sunday, 10 June 2018 at 17:59:12 UTC, Joe wrote:
That worked but now I have a more convoluted case: a C array of 
pointers to int pointers, e.g.,


int **xs[] = {x1, x2, 0};
int *x1[] = {x1a, 0};
int *x2[] = {x2a, x2b, 0};
...
int x2a[] = { 1, 3, 5, 0};

Only the first line is exposed (and without the 
initialization). So I tried:


extern(C) __gshared extern int**[1] xs;

The D compiler accepts that, but just about any manipulation 
gets screamed at, usually with Error: only one index allowed to 
index int. Note that I'm trying to access the ints, i.e., in C 
something like xs[1][0][2] to access the 5 in x2a. Do I have to 
mimic the intermediate C arrays?


I don't know why I didn't try this first.  It seems that the D 
equivalent of C's xs[1][0][2] is simply xs.ptr[[1][0][2].


Re: Access to structures defined in C

2018-06-10 Thread Joe via Digitalmars-d-learn

On Wednesday, 14 March 2018 at 02:17:57 UTC, Adam D. Ruppe wrote:
The type system would *like* to know, certainly for correct 
range errors, but if you declare it as the wrong length and use 
the .ptr, it still works like it does in C:


extern(C) __gshared extern char*[1] files; // still works

import core.stdc.stdio;

void main() {
printf("%s\n", files.ptr[2]); // ptr bypasses the range 
check

}



That worked but now I have a more convoluted case: a C array of 
pointers to int pointers, e.g.,


int **xs[] = {x1, x2, 0};
int *x1[] = {x1a, 0};
int *x2[] = {x2a, x2b, 0};
...
int x2a[] = { 1, 3, 5, 0};

Only the first line is exposed (and without the initialization). 
So I tried:


extern(C) __gshared extern int**[1] xs;

The D compiler accepts that, but just about any manipulation gets 
screamed at, usually with Error: only one index allowed to index 
int. Note that I'm trying to access the ints, i.e., in C 
something like xs[1][0][2] to access the 5 in x2a. Do I have to 
mimic the intermediate C arrays?



But if you can match the length, that's ideal.


Unfortunately, although the C array lengths are known at C 
compile time, they're not made available otherwise so I'm afraid 
the [1] trick will have to do for now.




Re: unittests, dub and libraries

2018-03-27 Thread Joe via Digitalmars-d-learn
On Wednesday, 28 March 2018 at 03:07:23 UTC, Jonathan M Davis 
wrote:

Run

dub test

The problem is that an executable needs a main, and a library 
doesn't have one, whereas when you're testing a library, you 
need an executable. So, a main must be inserted - e.g. with the 
-main flag to dmd. Just building the unittest build doesn't 
insert one. However, dub test _does_ deal with that for you.


Thanks.


unittests, dub and libraries

2018-03-27 Thread Joe via Digitalmars-d-learn
I'm trying to build a very simple library. For now it just has a 
single class, constructor, destructor and one method.  I added a 
unit test right after the method, declared the targetType to be 
"library" and a buildType of "unittest" (with options 
"unittests", "debugMode", "debugInfo"). When I run


  dub run -b unittest

it builds the library, but then says:

  Target is a library. Skipping execution.

If I compile with ldc2 -unittest the linker throws the error:

  (.text+0x20): undefined reference to `main'

If I add an empty main function to the source file, ldc2/gcc 
manage to create an executable that can be invoked manually and 
it runs through the unit test.


Is this the best that can be done?


Re: core.stdc.stdlib._compare_fp_t and qsort

2018-03-18 Thread Joe via Digitalmars-d-learn

On Sunday, 18 March 2018 at 19:01:11 UTC, Joe wrote:
I managed to get it working by declaring a D dynamic array, 
appending n_recs pointers to it and using it as argument to 
sort. Unfortunately, I then had to copy from the dynamic array 
to the fixed array in order to continue using the latter. Any 
shortcuts around this?


I just saw your other reply.  Passing recs[0..n_recs] does the 
trick. Thanks.


Re: core.stdc.stdlib._compare_fp_t and qsort

2018-03-18 Thread Joe via Digitalmars-d-learn

On Sunday, 18 March 2018 at 18:11:02 UTC, Dmitry Olshansky wrote:
Well since recs is array of pointers this looks like a null 
pointer in your data.


The usual ways to fix that is either print stuff or poke around 
in debugger to see if a Record* is null or .name is null.


The problem is that although the "recs" array is declared as 
having 10 pointers, not all pointers are used.  In the qsort 
case, the second argument limited the sort to just the first 
n_recs (valid) pointers. There doesn't seem to be a way to tell 
std.algorithm.sorting.sort to only look at part of the fixed 
array.


I managed to get it working by declaring a D dynamic array, 
appending n_recs pointers to it and using it as argument to sort. 
Unfortunately, I then had to copy from the dynamic array to the 
fixed array in order to continue using the latter. Any shortcuts 
around this?




Re: core.stdc.stdlib._compare_fp_t and qsort

2018-03-18 Thread Joe via Digitalmars-d-learn

On Sunday, 18 March 2018 at 13:10:08 UTC, Dmitry Olshansky wrote:

Do this to get the usual ptr + length:

sort!((a, b) => to!string((*a).name) < 
to!string((*b).name))(recs[]);


Also to!string would be computed on each compare anew. May want 
to use schwartzSort to avoid that, on 10 elements there is no 
real difference though.


The 10 elements are just because it's a small test program.

What does changing "recs" to "recs[]" as the argument actually 
do?  Does it duplicate the fixed array on the fly? [I guess I 
have to study more!]


The change does pass the compiler, but at runtime it causes a 
segfault.  The next to last frame in the backtrace shows (having 
changed from to!string to fromStringz and using a string template 
instead of a lambda):


#6  0x55565760 in 
std.algorithm.sorting.sort!("fromStringz((*a).name.ptr) < 
fromStringz((*b).name.ptr)", 0, 
testd.Record*[]).sort(testd.Record*[]) (r=...)


Then it goes through quickSortImpl, shortSort and sort5, moving 
on to either std.functional.binaryFun or processing of the 
lambda, with a and b equal to 0, ending with a segfault in a ?? 
call from fromStringz or in memcpy called from object._dup (in 
the to!string case).


Re: core.stdc.stdlib._compare_fp_t and qsort

2018-03-18 Thread Joe via Digitalmars-d-learn

On Monday, 12 March 2018 at 03:50:42 UTC, Joe wrote:

On Monday, 12 March 2018 at 03:13:08 UTC, Seb wrote:
Out of interest: I wonder what's your usecase for using qsort. 
Or in other words: why you can't use the high-level 
std.algorithm.sorting.sort?


This is only temporary. I will be using 
std.algorithm.sorting.sort. I was converting a C program and it 
annoyed me that I couldn't get the qsort invocation past the D 
compiler.


Now that I'm trying to use std.algorithm.sorting, I'm again 
puzzled by what I need to use for the "less" predicate. My first 
try was:


   sort!((a, b) => to!string((*a).name) < 
to!string((*b).name))(recs);


This results in the error:

Error: template std.algorithm.sorting.sort cannot deduce function 
from argument types !((a, b) => to!string((*a).name) < 
to!string((*b).name))(Record*[10]), candidates are:

/usr/lib/ldc/x86_64-linux-gnu/include/d/std/algorithm/sorting.d(1851):std.algorithm.sorting.sort(alias less = "a < 
b", SwapStrategy ss = SwapStrategy.unstable, Range)(Range r) if ((ss == SwapStrategy.unstable && 
(hasSwappableElements!Range || hasAssignableElements!Range) || ss != SwapStrategy.unstable && hasAssignableElements!Range) 
&& isRandomAccessRange!Range && hasSlicing!Range && hasLength!Range)

which is not very helpful. It's a bit different from the "no 
function match" that Adam complains about, but I presume it's 
because now we're dealing with templates, and although the 
compiler finds a single candidate, it's not satisfactory but it 
can't tell the user anything further.


I've tried using fromStringz((*x).name.ptr) instead of to!string 
(I'm still unclear to what extent can templates be used within 
templates).  I also tried using an explicit cast(Record *)x 
because I'm also unsure that type information is passed down.  
Neither change helped.


Access to structures defined in C

2018-03-13 Thread Joe via Digitalmars-d-learn
What is the correct way to declare and access storage managed by 
C?


For example, say a C module defines an array of filenames, e.g.,

char *files[] = { "one", "two", "three", 0};

The C header of course declares this as:

extern char *files[];

The way to declare it in a D module appears to be:

extern (C) {
   __gshared extern char *[] files;
}

However, trying to index into this, e.g.,

char *filename = files[1];

does not work.  In gdb if I try to examine 'filename' I see 
something like a reverse text string but treated as an 
(inaccessible) address and calling fromStringz causes a segfault.


Re: core.stdc.stdlib._compare_fp_t and qsort

2018-03-11 Thread Joe via Digitalmars-d-learn

On Monday, 12 March 2018 at 03:13:08 UTC, Seb wrote:
Out of interest: I wonder what's your usecase for using qsort. 
Or in other words: why you can't use the high-level 
std.algorithm.sorting.sort?


This is only temporary. I will be using 
std.algorithm.sorting.sort. I was converting a C program and it 
annoyed me that I couldn't get the qsort invocation past the D 
compiler.


Re: core.stdc.stdlib._compare_fp_t and qsort

2018-03-11 Thread Joe via Digitalmars-d-learn

On Monday, 12 March 2018 at 01:45:54 UTC, Adam D. Ruppe wrote:
I just reformatted it but now the difference should be visible: 
`extern(C)` is missing on your callback.


The scope things might make a difference too, but I know for 
sure extern(C) is necessary on your callback function.


I saw the extern(C) and I believe I tried it before my previous 
post, but dismissed it because I saw no difference in compiler 
behavior.  In any case declaring


extern (C) int compar(const (void *) p1, const (void *) p2) {
   ... // as before
}

still gives the error:

function core.stdc.stdlib.qsort (scope void* base, ulong nmemb, 
ulong size, extern (C) int function(scope const(void*), scope 
const(void*)) @system compar) is not callable using argument 
types (void*, ulong, ulong, extern (C) int function(const(void*) 
p1, const(void*) p2))


It only went away with

extern (C) int compar(scope const (void *) p1, scope const (void 
*) p2)


Could you explain or direct me to something that elucidates why 
the "scope" qualifiers are needed?  And is there something else 
that is necessary inside compar() or are the "scope"s just for 
decorative purposes?


Joe


Re: core.stdc.stdlib._compare_fp_t and qsort

2018-03-11 Thread Joe via Digitalmars-d-learn

On Sunday, 11 March 2018 at 23:26:04 UTC, Stefan Koch wrote:

You have to pass a pointer to the function.
Otherwise it'll be a parenthsis-less call.
use :  qsort(recs, num_recs, (Record *).sizeof, );


After passing a pointer, getting some other error messages, I 
changed the call to


qsort(cast(void *)recs, num_recs, cast(size_t)(Record 
*).sizeof, );


and the latest error is:

Error: function core.stdc.stdlib.qsort (scope void* base, ulong 
nmemb, ulong size, extern (C) int function(scope const(void*), 
scope const(void*)) @system compar) is not callable using 
argument types (void*, ulong, ulong, int function(const(void*) 
p1, const(void*) p2))


I fail to see which argument is causing the problem now.

Joe


core.stdc.stdlib._compare_fp_t and qsort

2018-03-11 Thread Joe via Digitalmars-d-learn

I'm getting a compiler error in a qsort() call as follows:

qsort(recs, num_recs, (Record *).sizeof, compar);

Record is a struct, recs is a fixed array of pointers to Record's 
and num_recs is a size_t that holds the number of valid records.


compar is this:

int compar(const void *p1, const void *p2)
{
import core.stdc.string : strcmp;
const Record **rp1 = cast(Record **)p1;
const Record **rp2 = cast(Record **)p2;

return strcmp((*rp1).name.ptr, (*rp2).name.ptr);
}

The error is: Error: function testd.compar (const(void*) p1, 
const(void*) p2) is not callable using argument types ()


I don't quite understand what those parentheses mean: is it 
implying "no arguments" and if so, where would one provide 
arguments?


Joe


Re: Understanding the AST...

2018-02-22 Thread joe via Digitalmars-d-learn

On Thursday, 22 February 2018 at 14:53:11 UTC, Seb wrote:

On Tuesday, 6 February 2018 at 12:03:06 UTC, joe wrote:

Hello everybody!

Last week end I found this post ( 
https://dlang.org/blog/2017/08/01/a-dub-case-study-compiling-dmd-as-a-library/ ) on the Blog and thought to myself awesome.


[...]



BTW I know it's not as powerful as DMD (and not the real 
thing), but often the AST XML dump from DScanner helps to 
deepen the understanding:


https://github.com/dlang-community/D-Scanner#ast-dump

You can even play with libdparse on the web:

https://run.dlang.io/is/qZsGDD


Hello Seb,

I had a look at the resources you provided and they are quite 
useful. Thank you.


However, while technically a lexer would be enough to solve the 
problem at hand, I think I'm going to want that full front-end a 
bit later.


The more information, the better. I rather have the option to 
ignore something I don't need than to need something I don't have 
:)





Re: Understanding the AST...

2018-02-22 Thread joe via Digitalmars-d-learn

On Thursday, 22 February 2018 at 13:44:51 UTC, RazvanN wrote:

On Thursday, 22 February 2018 at 13:21:04 UTC, joe wrote:

[...]


Indeed, @Stefan is right. The ParseTimeVisitor only contains 
information available at parse time. If you are interested in 
the parent you have 2 options: either (1) use the 
ParseTimeVisitor and implement the AST traversal logic yourself 
or (2) you can use the SemanticTimeTransitiveVisitor in which 
case the parent is not going to be null. In the case of (2) you 
need to also do some semantic analysis (so you need the whole 
dmd library, not just the parsing one). Here's an example on 
using the dmd library (including semantic) [1]. You can copy 
paste that example and add a few lines of code where you 
instantiate your visitor (which will inherit 
SemanticTimeTransitiveVisitor).


[...]


awesome, that helps a lot!

Thanks both of you :)


Re: Negative index range violation

2018-02-22 Thread joe via Digitalmars-d-learn
On Thursday, 22 February 2018 at 02:41:30 UTC, Steven 
Schveighoffer wrote:

On 2/21/18 7:30 PM, SrMordred wrote:
But with a slice negative indexes are never allowed, even on 
a pointer.



youd have to do
(c-1)[0 .. 1];


Nice!
Thank you both!

In D Slice article it says "You can even use negative 
indexes!" so I thought

that the [-1..x] should work too :)




Hah! I never thought of doing a slice with negative indexes ;)

/SNIP

-Steve


At night I dream about doing something like this

auto pos = haystack.find(needle);
auto something = haystack[pos..+3];  // meaning [pos..pos+3]
auto somethingElse = haystack[pos..-3];  // and [pos..pos-3] 
respectively


:)


Re: Understanding the AST...

2018-02-22 Thread joe via Digitalmars-d-learn

On Monday, 12 February 2018 at 08:47:58 UTC, RazvanN wrote:

Hi Joe,

/SNIP

On Tuesday, 6 February 2018 at 12:03:06 UTC, joe wrote:

[...]


The FuncDeclaration node contains all the information for that.
For example, you can access fd.parent to see if the function is
declared at top-level (in which case, the parent is going to be 
a module
declaration ) or if it is a nested function (in a class, in a 
struct, in a function).
Every AST node contains information about the position in the 
AST, all you
have to do is find how to get that information: which field to 
access or which

member function to call.

/SNIP

Cheers,
RazvanN


Follow up question...

Why is *.parent always null?
e.g.:

extern(C++) class MyVisitor(AST): ParseTimeTransitiveVisitor!AST
{
  override void visit(AST.Import i)
  {
assert(i.parent is null); // always true
  }

  override void visitFuncBody(AST.FuncDeclaration f)
  {
assert(f.parent is null); // always true
  }
}


Re: Understanding the AST...

2018-02-22 Thread joe via Digitalmars-d-learn

On Monday, 12 February 2018 at 08:47:58 UTC, RazvanN wrote:

Hi Joe,

I suggest you watch this video which explains how the parse 
time visitors work: https://www.youtube.com/watch?v=tK072jcoWv4 
.


On Tuesday, 6 February 2018 at 12:03:06 UTC, joe wrote:

[...]


The FuncDeclaration node contains all the information for that.
For example, you can access fd.parent to see if the function is
declared at top-level (in which case, the parent is going to be 
a module
declaration ) or if it is a nested function (in a class, in a 
struct, in a function).
Every AST node contains information about the position in the 
AST, all you
have to do is find how to get that information: which field to 
access or which

member function to call.


[...]


The function average length visitor inherits a transitive 
visitor
which means that the AST traversal logic is already implemented 
for you.
All you have to do is override the visiting methods of interest 
and do
whatever suits you : print stuff, alter the ast, stop the 
visitation or

continue the visitation (by calling super.visit(ASTnode)).


[...]


I know that my explanations might not be very explicit, but if 
you have an example please post it and we can work on it.


Cheers,
RazvanN


Hello RazvanN,

thank you very much for taking the time to reply and also your 
effort in making this happen.


I watched the video you linked and read your reply over and over, 
yet I still have a hard time to wrap my head around this idea.


Like for example DHTML DOM is very easy for me to grasp. It's 
like riding the car down the country road and I know where I am 
and which town I'm going to be next, etc.


This AST thing is more like a teleporter room on the Enterprise. 
Scotty activates the teleporter and a canister appears an a spot 
labeled imports. He repeats and a canister appears on a spot 
labeled functions, etc.


I will try again...


Understanding the AST...

2018-02-06 Thread joe via Digitalmars-d-learn

Hello everybody!

Last week end I found this post ( 
https://dlang.org/blog/2017/08/01/a-dub-case-study-compiling-dmd-as-a-library/ ) on the Blog and thought to myself awesome.


So I built the library and everything went smooth. Thanks for the 
effort of all the involved people who made that possible!


I've had a look at the 2 examples, too, the avg. function lines ( 
https://github.com/dlang/dmd/blob/master/src/examples/avg.d ) and 
the import ( 
https://github.com/dlang/dmd/blob/master/src/examples/impvisitor.d ) ones and for a start I decided to make a program that prints the outline of a module.


Turns out I don't really understand how to access the data in the 
AST.
For everything there's a visitor method and overriding a few of 
them to print return statements and some such works as advertised.


However, I have no idea where I am in the tree when any of those 
methods are called.
Like for example in 
FunctionLengthVisitor(AST).visitFuncBody(AST.FuncDeclaration fd).
I have a function declaration object which tells me everything 
about what's inside the function, but how do I know what or where 
this function belongs to, where can I get that information ? I 
don't see anything about UDAs either, nor the doc comment.


I understand when visitor.getAvgLen is called with the parsed 
module, the accept function calls a visitor overload for each 
member.
But this sounds to me like I'd have to do a lot of book keeping 
in my visitor to keep track of things which are already present 
in the AST.


Any insight to this would be much appreciated :)


Further questions on interfacing to Postgres libpq

2018-01-26 Thread Joe via Digitalmars-d-learn
An example test program that I'm using to learn D to C 
interfacing (specifically calling the libpq library) has a call 
to a C function declared as follows:


void PQprint(FILE *fout,  /* output stream */
 const PGresult *res,
 const PQprintOpt *po);

PQprintOpt is a struct whose first six members are declared as 
'pqbool' which is in turn declared as "typedef char pqbool;" in 
the distributed Postgres header file. I've defined an "alias 
pqbool = char;" in the D file, which is pretty straightforward.


The second of the six members has the name "align", which is a D 
keyword. So I renamed it "align_" and I presume that won't cause 
any problems.


To deal with the first argument to PQprint, I added "import 
core.stdc.stdio : FILE;".  The question is how to pass the D 
"stdout" as that argument.  The D compiler tells me I can't pass 
it as is (as was done in C), because in D it's of type "File".


Re: Using Postgres connection functions

2018-01-20 Thread Joe via Digitalmars-d-learn

On Saturday, 20 January 2018 at 04:54:47 UTC, Adam D. Ruppe wrote:

Same as above. The general pattern is:

C_Type[] name = new C_Type[](requested_size);
// pass as `name.ptr`. This becomes a C_Type*


Thanks, Adam. Perhaps something like this ought to make its way 
into the "D for C Programmers" page.


Re: Using Postgres connection functions

2018-01-19 Thread Joe via Digitalmars-d-learn

On Saturday, 13 January 2018 at 05:28:17 UTC, Joe wrote:
Going beyond the connection, there are various other libpq 
functions that use a similar pattern of values passed using 
multiple parallel C arrays, e.g.,


   PGresult *PQexecParams(PGconn *conn,
   const char *command,
   int nParams,
   const Oid *paramTypes,
   const char * const *paramValues,
   const int *paramLengths,
   const int *paramFormats,
   int resultFormat);

Each of the `paramXxxxs' arguments are arrays (Oid is an alias 
for uint).

[...]


Focusing on the above function, suppose the first two parameter 
arrays are defined in a C program as:


Oid paramTypes[] = {23, 25};
char *paramValues[] = {"1", "abcde"};

which could be expressed in D as:

Oid [] paramTypes = [23, 25];
string [] paramValues = ["1", "abcde"];

I know the paramTypes could be passed as null, letting PG deduce 
the data types but suppose we have some reason to accumulate 
types, etc., in D slices.  I know the paramValues can be 
manipulated in a manner similar to the one shown in my first 
post, namely something like this:


   extern(C) char * [2] pvs;
   foreach (i, val; paramValues)
   pvs[i] = cast(char *)toStringz(val);

And then use "cast(const char **)pvs" for the paramValues 
argument. The only feedback that I received that was explicit to 
this approach was in response to my initial post, in which Adam 
D. Ruppe said that what I did was "decent".


So I have two lingering doubts:

1. Is malloc() the only way to allocate the arrays, either of 
Oid's, int's or char *'s, for passing to the libpq functions?  
IOW, isn't there a way to take advantage of D's 'new' (and thus 
the GC)?


2. How to convert a slice of Oid's or int's to an array of 
pointers suitable by processing by the libpq C function?  A 
technique similar to the previous one seems to work, e.g.,


extern(C) Oid [2] pts;
foreach (i, typ; paramTypes)
pts[i] = typ;

But I'm not sure if it's really working (when I mistakenly had a 
* in the pts declaration, at one point it also seemed to work).


Re: Using Postgres connection functions

2018-01-15 Thread Joe via Digitalmars-d-learn

On Monday, 15 January 2018 at 02:28:29 UTC, Matthias Klumpp wrote:
In any case, please don't start another Postgres library and 
consider contributing to one of the existing ones, so that we 
maybe have one really awesome, 100% complete library at some 
point.


If, on the other hand, your goal is to learn about the 
low-level Postgres interface and not just to have a Postgres 
interface for an application you develop, by all means, play 
with it :-)


At this point, I am indeed learning about low-level Postgres 
interfaces (but not so low-level as the client-server protocol) 
as a way to understand the challenges of interfacing D to C.


However, as part of the Pyrseas open source project, which I 
maintain, I had started to create a Postgres interface in Python 
inspired by The Third Manifesto, as opposed to ORMs like 
SQLAlchemy (see 
https://pyrseas.wordpress.com/2013/03/07/a-pythonic-ttm-inspired-interface-to-postgresql-requirements/). I got criticized for "reinventing the wheel" but I believe TTM, if properly done, is quite different from an ORM.


I understand your concern about not starting another PG library. 
From the cursory investigation of the existing libraries, I think 
they span a spectrum, with ddb at one end (low-level protocol), 
then derelict-pq (low-level binding over libpq), ddbc at the 
opposite end (multi-DBMS support) and several others in between. 
So I  guess the real problem is with the proliferation in the 
latter group.


Re: Using Postgres connection functions

2018-01-13 Thread Joe via Digitalmars-d-learn
On Saturday, 13 January 2018 at 10:10:41 UTC, Jacob Carlborg 
wrote:
There's a native D library, ddb [1], for connecting to 
Postgres. Then you don't have to worry about null-terminated 
strings.


There are several D libraries that I would consider "native": 
derelict-pq, dpq, dpq2 and ddb. The latter perhaps has the 
distinction that it doesn't use libpq, but rather implements the 
Postgres FE/BE protocol. That's a bit *too* native for my taste. 
It means the library maintainer has to keep up with changes to 
the internal protocol, which although published, the Postgres 
group doesn't have to maintain compatibility from version to 
version. For example, they haven't dropped the PQsetdbLogin 
function even though the PQconnectdb and PQconnectdbParams 
functions are obviously preferred. OTOH, there used to be an 
AsciiRow message format in the protocol, that was dropped, 
unceremoniously (not even mentioned in the release notes).




Re: Using Postgres connection functions

2018-01-12 Thread Joe via Digitalmars-d-learn
Going beyond the connection, there are various other libpq 
functions that use a similar pattern of values passed using 
multiple parallel C arrays, e.g.,


   PGresult *PQexecParams(PGconn *conn,
   const char *command,
   int nParams,
   const Oid *paramTypes,
   const char * const *paramValues,
   const int *paramLengths,
   const int *paramFormats,
   int resultFormat);

Each of the `paramXxxxs' arguments are arrays (Oid is an alias 
for uint).


   PGresult *PQprepare(PGconn *conn,
const char *stmtName,
const char *query,
int nParams,
const Oid *paramTypes);

   PGresult *PQexecPrepared(PGconn *conn,
 const char *stmtName,
 int nParams,
 const char * const *paramValues,
 const int *paramLengths,
 const int *paramFormats,
 int resultFormat);

My point is that there seems to be a need to have a generic or 
generalized mechanism for passing these argument arrays from D to 
C.


Re: Using Postgres connection functions

2018-01-12 Thread Joe via Digitalmars-d-learn

On Saturday, 13 January 2018 at 04:26:06 UTC, Adam D. Ruppe wrote:

If and only if the values are known at compile time, you can do:

const char** keywords = ["hostaddr".ptr, "port".ptr, 
"dbname".ptr, null].ptr;


or even do it inline:


PQconnectdbParams(["hostaddr".ptr, "port".ptr, "dbname".ptr, 
null].ptr, ditto_for_values, 1);


The keywords are (or could be) known at compile time, but almost 
by definition, the associated values are only known at runtime.




Using Postgres connection functions

2018-01-12 Thread Joe via Digitalmars-d-learn
I'm trying to learn how to use D to connect (and send queries) to 
Postgres, i.e., libpq in C. Postgres has three families of 
connection functions: PQsetdbLogin which takes multiple 
individual arguments (all as const char *), PQconnectdb which 
takes a single connection string (which Postgres then has to 
parse into keywords/values) and PQconnectdbParams (introduced 
with PG 9.0 in 2010) which takes two arrays of char pointers, one 
for the keywords and another for the values, i.e., it's 
pre-parsed, and I believe, more convenient for callers since it's 
most likely that they get the parameter values from command line 
arguments, environment values or UI dialogs, so it saves the 
connection string formatting on the caller side and the 
parsing/decomposing on the library side.


In spite of the latter considerations, it appears most D 
libraries for Postgres only support connection string usage (only 
derelict-pq has a declaration for PQconnectdbParams--but I 
haven't tested it).


In any case, I tried to use PQconnectdbParams by first declaring 
it, as per the Postgres manual, with


extern(C)
{
struct PGconn;

PGconn *PQconnectdbParams(const char * const * keywords,
  const char * const * values,
  int expand_dbname);
}

This caused ldc2, on Linux, to complain as follows:

connection.d(30): Error: found 'const' when expecting ')'
connection.d(30): Error: semicolon expected following function 
declaration

connection.d(30): Error: declaration expected, not '*'

It only compiled after I removed the second 'const' in the first 
and second arguments.


The hard thing was figuring out how to pass the keyword/values 
arrays, defined as:


string[] keywords = ["hostaddr", "port", "dbname"];
string[] values = ["127.0.0.1", "5432", "testdb"];

to the D invocation of PQconnectdbParams.  I ended up with the 
following, which looks like covering a patient with lots of 
bandaids and looking the other way (and I had to modify the 
arrays above with a fixed length).


extern(C) char * [keywords.length + 1] kws;
extern(C) char * [keywords.length + 1] vals;
foreach (i, k; keywords) {
kws[i] = cast(char *)toStringz(k);
vals[i] = cast(char *)toStringz(values[i]);
}
kws[keywords.length] = null;  // Postgres wants the NULL 
termination

vals[keywords.length] = null;

conn = PQconnectdbParams(cast(const char **)kws,
 cast(const char **)vals, 1);

I assume that in a real program I'd have to malloc the C arrays, 
since I wouldn't know beforehand how many parameters there would 
be (or I could define them with a static size of about 30 since 
that's how many connection parameters are recognized currently).


So my question is: is there an easier or better way of passing 
two arrays of C null-terminated strings to an extern(C) function?