ncurses api with the D Programming Language
Asked Answered
S

4

10

I am trying to teach myself AI using neural networks. Long story short, I wanted to create a simple graphic that would display what is happening in my program using ncurses. The tutorial that I am using is found here.

I was under the impression that D was compatible with C and I could theoretically call C functions relatively easily.

I find that not to be the case. I am a relatively novice programmer, so even the simplistic explanations are a little above my head. I found this here.

D is designed to fit comfortably with a C compiler for the target system. D makes up for not having its own VM by relying on the target environment's C runtime library. It would be senseless to attempt to port to D or write D wrappers for the vast array of C APIs available. How much easier it is to just call them directly.

This is done by matching the C compiler's data types, layouts, and function call/return sequences.

That sounds wonderful. A little bit over my head. I tested and got a simple C program working:

#include <curses.h>

int main(void) {
    int ch;

    initscr();
    noecho();
    cbreak();
    printw("Hit Ctrl+C to exit ...\n\n");
    for (;;) {
      ch = getch();
      printw("Value of char: %d (%02x)\n", ch, ch);
    }
    endwin();
    return 0;
}

shamelessly copied and pasted from another question on SO. At least I did my homework.

I tried basically the same thing from a simple D program. I got this error:

Error: module curses is in file 'curses.d' which cannot be read

I am absolutely positive that I am trying something really stupid.

Is there an easy way to use ncurses in a D program?

I'm running on zero sleep and caffeine, so please be gentle! Even a link to a website would be greatly appreciated!

I probably didn't include everything that I should have, so AMA.

And feel free to insult my intelligence.

Stepper answered 14/10, 2011 at 22:47 Comment(5)
Ok, so there is my comment up there about how D should just be able to call C, and then again on the very same site, It's claimed that you will have to rewrite the .h files to be .d files. That is apparently a pretty big difference... I'm leaning towards the second, since there is a special windows tool that is supposed to help automate the process of translating the header files. htod it's called. Unfortunately it's windows only. I'm beginning to realize how fractured the D community really is...Stepper
ok, so it's possible to link D with a C library. Provided that you didn't happen to name functions the same. (it was main(). facepalm). the problem is, you still need to convert the header file... So technically it IS possible to call C functions 'easily' and without having to resort to a wrapper. But what they leave out is that you have to convert the .h file to a .d file since D does not implement the CPP. Great. Have you SEEN the .h file I want to convert? it is literally nothing but a thousand lines of #ifndefs and #Pragmas.Stepper
I wouldn't say that the complication is hidden, it just isn't expressed more than needing to convert .h to .d, which those familiar with C know isn't going to be simple. And ncurses is pretty much a macro library as you probably noticed. You can run the CPP against a file and have it output the C which is much easier to convert, but still may not be correct. Anyway good work.Hollingshead
Oh, I noticed. I definitely noticed. =P Do know know how to get gcc to output that? I tried a bunch of variations, but mostly I get object code, or something not readable.. funny thing that I found on the source of ncurses: // vile:cppmodeStepper
network-theory.co.uk/docs/gccintro/gccintro_36.htmlHollingshead
S
3

Ok, I feel I have been spamming a little, but I hope that all of the info will be useful in the future.

I found a project name ycurses. I discovered the problem with TLS is specific to D2. I changed the files to work with D2. dmd, gdc, it all works. I finally have my ncurses using D! It just took a long weekend of marathon coding and researching.

Since the code I found is old and appears to be abandoned, I am now hosting it on github

Even though the code states it will work with Tango, IT WILL NOT. I'll probably fix that some time this week.

The code has a nice little tutorial included, as well as instruction on how to link. Your welcome. I feel very accomplished all of a sudden.

Stepper answered 16/10, 2011 at 15:14 Comment(2)
It is sad you have had to go through so many difficulties during first D tryout. You see, calling C code from D IS trivial, it is just not novice-friendly at all as it involves variety of advanced topics. Understanding ABI and being able to mix GC and non-GC code at least. And it definitely is easier in comparison to most other languages.Diazotize
This is true, most of my difficulties stemmed from my deep ignorance of everything programming related. Hopefully I included enough information and links so that other novices can use my experience to learn from. I do not think that it is sad, as D has forced me to learn more in a weekend than I learned in two years of programming classes at university. I regret nothing.Stepper
S
6

Ok, after about 8 hours of digging through this crap I have determined that it is indeed possible to call C functions natively.

HOWEVER, it is also stated that "It would be senseless to attempt to port to D or write D wrappers for the vast array of C APIs available. How much easier it is to just call them directly."

Yeah, I'm going to call BS on that one. You DO have to port to D. Is it not considered porting when you are going from a macro enabled preprocessing .h file to a .d file? It is definitely nontrivial. So in my opinion they are intentionally leaving out the hard part and trying to make it look way better than it actually is.

In case anyone is wondering, If you have a C api that you would like to call in your D code: go grab the header file and attempt to convert it to something that D can read. Then simply compile your code, importing your new .d file, and linking it with whatever you are interfacing with. If you did it right, it'll work and you'll now have lots of memory leaks.

In my opinion, unless you need the entire library, save yourself a headache and just link a small C wrapper to your D code. You grab only what you need, and you have the added benefit of being able to rename stuff to whatever you want.

There are a couple of projects to help automate the process of translating header files. dtoh for windows only, and bcd which is found on dsource. bcd also includes bindings for curses! they are listed as being alpha only, but they seem to be working. I'm trying to call their curses.d file from my main.d file and I've been getting:

main.d:13: Error: cannot implicitly convert expression ("ype any character to see it in bold\x0a") of type string to char[]
main.d:15: Error: function aphrodite.curses.printw (char*,...) is not callable using argument types (char[])
main.d:15: Error: cannot implicitly convert expression (stuff) of type char[] to char*
main.d:20: Error: function aphrodite.curses.printw (char*,...) is not callable using argument types (string)
main.d:20: Error: cannot implicitly convert expression ("F1 Key pressed") of type string to char*
main.d:26: Error: function aphrodite.curses.printw (char*,...) is not callable using argument types (string)
main.d:26: Error: cannot implicitly convert expression ("The pressed key is ") of type string to char*
main.d:28: Error: function aphrodite.curses.printw (char*,...) is not callable using argument types (string,int)
main.d:28: Error: cannot implicitly convert expression ("%c") of type string to char*

so my problem lies in the way C handles strings and the way D handles strings. They don't match up and my extremely limited C knowledge doesn't tell me how to fix it. Luckily, for all the anti-documentation about calling C functions, there is quite a bit of info about how D types translate to C types.

I sincerely hope that someone finds this helpful somewhere down the line.

Stepper answered 15/10, 2011 at 8:52 Comment(4)
I've "fixed" the string char* problem by simply removing them and deciding to fix that when it compiles and links correctly. So now my biggest problem is that I get this linker error:/usr/bin/ld: stdscr: TLS reference in main.o mismatches non-TLS definition in /usr/lib32/libcurses.so section .bss /usr/lib32/libcurses.so: could not read symbols: Bad value collect2: ld returned 1 exit status Now I just need to fix this..Stepper
ok, the TLS problem is caused by d2. In the name of promoting easy threading, they changed all variable to thread local storage by default, so I'd have yo change everything with no guarantee it'll fix my problems...Stepper
Regarding porting from C to D: what is being dismissed as senseless is porting the non header code. The {,semi-,non-}automatable task of generating bindings for the D compiler to work with is a different (and much simpler) task.Durante
I understand that now, but as you can see from my question, I really had absolutely no clue what I was doing. The lack of documentation made me frustrated, so most of what I said was meant to be 'gr! me no understand!' The document on D-Programming_Language was not very clear on what it was talking about, at least from the perspective of one who has little experience in these matters. But it probably wasn't written with my level of experience in mind anyways. Come to think of it, now that I know what I know, it makes a lot more sense. =PStepper
S
3

Ok, I feel I have been spamming a little, but I hope that all of the info will be useful in the future.

I found a project name ycurses. I discovered the problem with TLS is specific to D2. I changed the files to work with D2. dmd, gdc, it all works. I finally have my ncurses using D! It just took a long weekend of marathon coding and researching.

Since the code I found is old and appears to be abandoned, I am now hosting it on github

Even though the code states it will work with Tango, IT WILL NOT. I'll probably fix that some time this week.

The code has a nice little tutorial included, as well as instruction on how to link. Your welcome. I feel very accomplished all of a sudden.

Stepper answered 16/10, 2011 at 15:14 Comment(2)
It is sad you have had to go through so many difficulties during first D tryout. You see, calling C code from D IS trivial, it is just not novice-friendly at all as it involves variety of advanced topics. Understanding ABI and being able to mix GC and non-GC code at least. And it definitely is easier in comparison to most other languages.Diazotize
This is true, most of my difficulties stemmed from my deep ignorance of everything programming related. Hopefully I included enough information and links so that other novices can use my experience to learn from. I do not think that it is sad, as D has forced me to learn more in a weekend than I learned in two years of programming classes at university. I regret nothing.Stepper
S
1

Ok, there is a curses.d port? I don't know what to call it.. It is located here.

It still requires that you link against the ncurses library, but it works perfectly if you compile with the d1 dmd compiler. which seems to be kind of useless in my current project, so i've either got to port the files to d2 (not a bad idea, this project has long since been abandoned) or see if there is a way to link d1 compiles files, d2 compiled files and C. This would seem to me to be straight forward, but I also thought linking to C would be straightforward.

So after a few days and mostly trial-and-error style tests using files dated 7 years ago pulled from the internet, I finally got a simple hellp world compiled using the curses library.

I am strongly considering porting the dcurses files to D2 and hosting them myself... I just wish I had more experience with this type of thing...

Stepper answered 16/10, 2011 at 12:37 Comment(0)
A
-3

May I suggest having a look at Python? I know it's not D and is a completely different language but if your aim is to learn AI and don't insist on using D then Python is very good. It will allow you to do what you normally do in D in 1/10 of the time. ncurses in Python is an ease. I think there was some guy who wrote a tetris game in about 55 lines (which is standard).

Allergy answered 23/11, 2011 at 0:7 Comment(4)
yeah, but python also executes around 20 times slower (according to some estimates) If I want to write something large, or computationally intensive, that would slow me down. Plus I already (sort of) know python. =PStepper
Yes, you have to make that call. If execution time of a D/C++ program is 0.01s then 20 times slower is not that bad. Even if execution in C++ is 30s and in python 10 minutes it still might be worth it if it allows you to write what you want quickly. Another thing to use is (of course) Matlab/Octave. Bear in mind that C/C++/D are what I call expensive languages - they should only be used if you can't avoid it because all their performance comes at a price - development speed. For prototyping/learning Python/Matlab is (I think) fine.Allergy
Very True, very true. Use the best tool for the job.Stepper
You might also look at the lisp language family. It's easy to use like python but runs much, much faster. However, its library is nowhere near python library.Allergy

© 2022 - 2024 — McMap. All rights reserved.