www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - ImportC rocks!

reply Ki Rill <rill.ki yahoo.com> writes:
I tried using Raylib with importC, and I thought I should share 
my recent experience using it... Works like a charm! Worked from 
the first (second really) try!

What I did step by step (in case someone needs directions):

raylib.c:
```
#include "raylib.h"
```

main.d:
```
void main() {
     import raylib;

     InitWindow(640, 640, "ImportC raylib test");
     // game loop
     CloseWindow();
}
```

Compiling:
```
gcc -E raylib.c > raylib.i
dmd main.d raylib.c -L=-lraylib
./main
```

I really like the fact that dmd automatically picks up a name for 
the executable.

It was a pleasant experience using D when it actually 'just' 
works. There is still much to improve on ImportC, but I like that 
we slowly get there... when it's easily usable.
Mar 12 2022
next sibling parent reply IGotD- <nise nise.com> writes:
On Saturday, 12 March 2022 at 09:55:03 UTC, Ki Rill wrote:
 Compiling:
 ```
 gcc -E raylib.c > raylib.i
 dmd main.d raylib.c -L=-lraylib
 ./main
 ```
You run the preprocessor in gcc then call the output raylib.i but where is that file later used?
Mar 12 2022
parent Ki Rill <rill.ki yahoo.com> writes:
On Saturday, 12 March 2022 at 09:59:45 UTC, IGotD- wrote:
 On Saturday, 12 March 2022 at 09:55:03 UTC, Ki Rill wrote:
 Compiling:
 ```
 gcc -E raylib.c > raylib.i
 dmd main.d raylib.c -L=-lraylib
 ./main
 ```
You run the preprocessor in gcc then call the output raylib.i but where is that file later used?
That was a typo. Should've been: ``` gcc -E raylib.c > raylib.i dmd main.d raylib.i -L=-lraylib ./main ``` D does not have a C preprocessor. So we need to preprocess the C file ourselves before D can compile it.
Mar 12 2022
prev sibling next sibling parent reply Ki Rill <rill.ki yahoo.com> writes:
On Saturday, 12 March 2022 at 09:55:03 UTC, Ki Rill wrote:
 [...]
Thank you Walter and everyone else for adding importC to D. When I first looked at it, I didn't think it's something I would use (there are many bindings I could just `dub add` after all), but after trying it out... it feels like I've been freed... no need for bindings or wrappers that someone needs to maintain and that may get outdated.
Mar 12 2022
parent reply bachmeier <no spam.net> writes:
On Saturday, 12 March 2022 at 10:03:28 UTC, Ki Rill wrote:
 On Saturday, 12 March 2022 at 09:55:03 UTC, Ki Rill wrote:
 [...]
Thank you Walter and everyone else for adding importC to D. When I first looked at it, I didn't think it's something I would use (there are many bindings I could just `dub add` after all), but after trying it out... it feels like I've been freed... no need for bindings or wrappers that someone needs to maintain and that may get outdated.
While there's more work that needs to be done, it'll be nice to be able to do things like add an sqlite dependency without needing the end user to mess around with sqlite. You can already do that by compiling the header with ImportC and using a C compiler to compile the library. I'm looking forward to the day I can add sqlite as a Dub dependency and let D compile everything.
Mar 12 2022
parent reply Tejas <notrealemail gmail.com> writes:
On Saturday, 12 March 2022 at 15:26:02 UTC, bachmeier wrote:
 On Saturday, 12 March 2022 at 10:03:28 UTC, Ki Rill wrote:
 [...]
While there's more work that needs to be done, it'll be nice to be able to do things like add an sqlite dependency without needing the end user to mess around with sqlite. You can already do that by compiling the header with ImportC and using a C compiler to compile the library. I'm looking forward to the day I can add sqlite as a Dub dependency and let D compile everything.
What is wrong with using `etc.c.sqlite3`? https://dlang.org/phobos/etc_c_sqlite3.html
Mar 12 2022
parent reply rikki cattermole <rikki cattermole.co.nz> writes:
That gets you the binding, not the actual library itself.

What bachmeier is looking forward to is having libraries like sqlite, 
zlib, lua and sljit to be copiled with the D compiler rather than having 
to supply binaries or hope its installed in the user system.

This way it'll "just work" without needing to worry about external 
dependencies.
Mar 12 2022
next sibling parent reply StarCanopy <starcanopy protonmail.com> writes:
And thus, perhaps compiling druntime along with a libc? After 
all, I hear that statically linking with glibc is quite difficult.
Mar 12 2022
parent rikki cattermole <rikki cattermole.co.nz> writes:
On 13/03/2022 4:46 PM, StarCanopy wrote:
 And thus, perhaps compiling druntime along with a libc? After all, I 
 hear that statically linking with glibc is quite difficult.
I don't know, extensions alone probably would kill ImportC being of any help. At very least its a build management problem. Something[0] should help with. [0] https://wiki.dlang.org/Building_LDC_runtime_libraries
Mar 12 2022
prev sibling parent bachmeier <no spam.net> writes:
On Sunday, 13 March 2022 at 03:11:58 UTC, rikki cattermole wrote:
 That gets you the binding, not the actual library itself.

 What bachmeier is looking forward to is having libraries like 
 sqlite, zlib, lua and sljit to be copiled with the D compiler 
 rather than having to supply binaries or hope its installed in 
 the user system.

 This way it'll "just work" without needing to worry about 
 external dependencies.
Yeah, and it's not just the external dependency, but the version of that dependency. A good example with sqlite is the recent json functionality. If you include the sqlite source in your project, you can use all the latest and greatest.
Mar 13 2022
prev sibling next sibling parent reply zjh <fqbqrr 163.com> writes:
On Saturday, 12 March 2022 at 09:55:03 UTC, Ki Rill wrote:
 I tried using Raylib with importC, and I thought I should share
Maybe D can import Rust,`why not`?
Mar 12 2022
parent bachmeier <no spam.net> writes:
On Saturday, 12 March 2022 at 13:53:29 UTC, zjh wrote:
 On Saturday, 12 March 2022 at 09:55:03 UTC, Ki Rill wrote:
 I tried using Raylib with importC, and I thought I should share
Maybe D can import Rust,`why not`?
If it's a Rust library that can be called from C, then yes, D can call it by compiling the C header using ImportC. If you mean compiling Rust code, that would have a low benefit/cost ratio.
Mar 12 2022
prev sibling next sibling parent Walter Bright <newshound2 digitalmars.com> writes:
Good to see it working for ya!
Mar 14 2022
prev sibling parent reply Andrea Fontana <nospam example.com> writes:
On Saturday, 12 March 2022 at 09:55:03 UTC, Ki Rill wrote:
 I tried using Raylib with importC, and I thought I should share 
 my recent experience using it... Works like a charm! Worked 
 from the first (second really) try!

 What I did step by step (in case someone needs directions):

 raylib.c:
 ```
 #include "raylib.h"
 ```

 main.d:
 ```
 void main() {
     import raylib;

     InitWindow(640, 640, "ImportC raylib test");
     // game loop
     CloseWindow();
 }
 ```

 Compiling:
 ```
 gcc -E raylib.c > raylib.i
 dmd main.d raylib.c -L=-lraylib
 ./main
 ```
The big problem is that #define are missing. So a lot of const must be redefined or made explicit like: ray.h: ``` #include "raylib.h" Color RAYLIB_BLACK = BLACK; ``` But it's not so comfortable to use. I would like to mix different languages, just like kotlin+java on android development or like calypso did.
Mar 14 2022
next sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Mon, Mar 14, 2022 at 10:47:24AM +0000, Andrea Fontana via Digitalmars-d
wrote:
[...]
 I would like to mix different languages, just like kotlin+java on
 android development or like calypso did.
Have you checked out Adam's jni.d? Makes calling Java functions from D (and vice versa) so nice that it almost made me want to write Java again. :-P T -- Let's call it an accidental feature. -- Larry Wall
Mar 14 2022
prev sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 3/14/22 6:47 AM, Andrea Fontana wrote:
 On Saturday, 12 March 2022 at 09:55:03 UTC, Ki Rill wrote:
 I tried using Raylib with importC, and I thought I should share my 
 recent experience using it... Works like a charm! Worked from the 
 first (second really) try!

 What I did step by step (in case someone needs directions):

 raylib.c:
 ```
 #include "raylib.h"
 ```

 main.d:
 ```
 void main() {
     import raylib;

     InitWindow(640, 640, "ImportC raylib test");
     // game loop
     CloseWindow();
 }
 ```

 Compiling:
 ```
 gcc -E raylib.c > raylib.i
 dmd main.d raylib.c -L=-lraylib
 ./main
 ```
The big problem is that #define are missing. So a lot of const must be redefined or made explicit like: ray.h: ``` #include "raylib.h" Color RAYLIB_BLACK = BLACK;  ``` But  it's not so comfortable to use. I would like to mix different languages, just like kotlin+java on android development or like calypso did.
Yes, C does not allow manifest constants of anything other than integers via enum. Raylib has eschewed most (all?) #defines of integers, preferring enums, but e.g. a `Color` struct cannot be an enum. The pain of having to not only redeclare manifest constants but *also* give them a different name is pretty high. -Steve
Mar 14 2022
parent reply Andrea Fontana <nospam example.com> writes:
On Monday, 14 March 2022 at 13:30:44 UTC, Steven Schveighoffer 
wrote:
 Yes, C does not allow manifest constants of anything other than 
 integers via enum. Raylib has eschewed most (all?) #defines of 
 integers, preferring enums, but e.g. a `Color` struct cannot be 
 an enum.

 The pain of having to not only redeclare manifest constants but 
 *also* give them a different name is pretty high.

 -Steve
I can't belive compiler can't handle a simple optimization for a non-manifest color const. Is really a performance penalty to declare BLACK like this? ```c const struct Color BLACK = (Color){0,0,0,255 ```
Mar 14 2022
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 3/14/22 12:26 PM, Andrea Fontana wrote:
 On Monday, 14 March 2022 at 13:30:44 UTC, Steven Schveighoffer wrote:
 Yes, C does not allow manifest constants of anything other than 
 integers via enum. Raylib has eschewed most (all?) #defines of 
 integers, preferring enums, but e.g. a `Color` struct cannot be an enum.

 The pain of having to not only redeclare manifest constants but *also* 
 give them a different name is pretty high.
I can't belive compiler can't handle a simple optimization for a non-manifest color const. Is really a performance penalty to declare BLACK like this? ```c const struct Color BLACK = (Color){0,0,0,255 ```
You can submit your request to raylib, and see if they accept it. I doubt it. One thing that is very obvious from a few of my PRs is that raylib is not interested in making changes specifically to be binding-friendly. I think you will probably find this from many C libraries -- their focus is their library, not yours. If ImportC cannot work with C libraries as they stand without "simple tweaks", then it's just not going to be worth much. -Steve
Mar 14 2022
next sibling parent reply jmh530 <john.michael.hall gmail.com> writes:
On Monday, 14 March 2022 at 17:49:23 UTC, Steven Schveighoffer 
wrote:
 [snip]

 One thing that is very obvious from a few of my PRs is that 
 raylib is not interested in making changes specifically to be 
 binding-friendly. I think you will probably find this from many 
 C libraries -- their focus is their library, not yours. If 
 ImportC cannot work with C libraries as they stand without 
 "simple tweaks", then it's just not going to be worth much.

 -Steve
Would there be any benefit to having raylib-d take advantage of importC, rather than the user, but also keep around some of the things that make it easier to use, like the Colors enum?
Mar 14 2022
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 3/14/22 2:02 PM, jmh530 wrote:
 On Monday, 14 March 2022 at 17:49:23 UTC, Steven Schveighoffer wrote:
 [snip]

 One thing that is very obvious from a few of my PRs is that raylib is 
 not interested in making changes specifically to be binding-friendly. 
 I think you will probably find this from many C libraries -- their 
 focus is their library, not yours. If ImportC cannot work with C 
 libraries as they stand without "simple tweaks", then it's just not 
 going to be worth much.
Would there be any benefit to having raylib-d take advantage of importC, rather than the user, but also keep around some of the things that make it easier to use, like the Colors enum?
ImportC could replace much of the binding, sure. However, we have an additional problem in that raylib-d adds things to structs, such as operator overloads. That's not so easy to do. ImportC itself is great for things that you want to "just use". Again, though, it needs to provide some mechanism to access #define constants and macros. But as a D developer, using an actual C library gets quite annoying. You deal with it because it's what's available. But if I can add niceties to it, I'd rather do that. Raylib itself is such a simple and well-organized library that I've contemplated just rewriting it in D with a D-like interface (use strings, use overloading, operator overloads, etc). But contemplation is all I have time for unfortunately :( -Steve
Mar 14 2022
next sibling parent Steven Schveighoffer <schveiguy gmail.com> writes:
On 3/14/22 2:11 PM, Steven Schveighoffer wrote:

 But as a D developer, using an actual C library gets quite annoying. You 
 deal with it because it's what's available. But if I can add niceties to 
 it, I'd rather do that.
One possible usage of ImportC which I just thought of, would be to statically verify the raylib binding you have is compatible with the raylib source. So you build against raylib, including the .h file, and then you introspect all the functions/types in your raylib-d binding and the raylib c header, and if there are any mismatches, you report those. I would absolutely accept such a verification system as a PR to raylib-d! I did plant a seed in raylib that for the next released version, I can verify at runtime that you are bound to the correct version of the library -- that was accepted by Ray. -Steve
Mar 14 2022
prev sibling parent reply Elronnd <elronnd elronnd.net> writes:
On Monday, 14 March 2022 at 18:11:09 UTC, Steven Schveighoffer 
wrote:
 raylib-d adds things to structs, such as operator overloads. 
 That's not so easy to do.
struct DStruct { CStruct c_version; alias c_version this; DStruct op... }
Mar 14 2022
parent Steven Schveighoffer <schveiguy gmail.com> writes:
On 3/14/22 8:36 PM, Elronnd wrote:
 On Monday, 14 March 2022 at 18:11:09 UTC, Steven Schveighoffer wrote:
 raylib-d adds things to structs, such as operator overloads. That's 
 not so easy to do.
struct DStruct {     CStruct c_version;     alias c_version this;     DStruct op... }
clib.h: CStruct cFunction(); -Steve
Mar 14 2022
prev sibling parent reply Andrea Fontana <nospam example.com> writes:
On Monday, 14 March 2022 at 17:49:23 UTC, Steven Schveighoffer 
wrote:
 One thing that is very obvious from a few of my PRs is that 
 raylib is not interested in making changes specifically to be 
 binding-friendly. I think you will probably find this from many 
 C libraries -- their focus is their library, not yours. If 
 ImportC cannot work with C libraries as they stand without 
 "simple tweaks", then it's just not going to be worth much.

 -Steve
I see you're using dstep to generate bindings. Do you know there's a file with all the exports? Did you try to generate bindings from it? https://github.com/raysan5/raylib/blob/master/parser/raylib_api.json (json is not the only format available, check that folder). Andrea
Mar 15 2022
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 3/15/22 5:42 AM, Andrea Fontana wrote:
 On Monday, 14 March 2022 at 17:49:23 UTC, Steven Schveighoffer wrote:
 One thing that is very obvious from a few of my PRs is that raylib is 
 not interested in making changes specifically to be binding-friendly. 
 I think you will probably find this from many C libraries -- their 
 focus is their library, not yours. If ImportC cannot work with C 
 libraries as they stand without "simple tweaks", then it's just not 
 going to be worth much.
I see you're using dstep to generate bindings. Do you know there's a file with all  the exports? Did you try to generate bindings from it? https://github.com/raysan5/raylib/blob/master/parser/raylib_api.json (json is not the only format available, check that folder).
I did not know that, thanks for pointing it out! I'm going to stick with DStep for a few reasons: 1. Raylib's home-grown raylib-only header parser is probably not as mature as clang. 2. There isn't an already existing mechanism to parse these json files and produce D code. I'd have to write it. 3. Any tool that I write is useful for raylib, and nothing else. 4. Releases on raylib happen so infrequently, that the 30 minutes it takes for me to run dstep and the subsequent fixup is not a burden. If ImportC gets to the point where you can truly import C headers, then I might switch to something like that. -Steve
Mar 15 2022
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 3/15/2022 5:38 AM, Steven Schveighoffer wrote:
 If ImportC gets to the point where you can truly import C headers, then I
might 
 switch to something like that.
Please give it a try, and report any problems to Bugzilla!
Mar 17 2022
parent JN <666total wp.pl> writes:
On Friday, 18 March 2022 at 05:06:29 UTC, Walter Bright wrote:
 On 3/15/2022 5:38 AM, Steven Schveighoffer wrote:
 If ImportC gets to the point where you can truly import C 
 headers, then I might switch to something like that.
Please give it a try, and report any problems to Bugzilla!
Is there any documentation on how to use importC with dub? I have a project using wgpu-native bindings which I've been generating with Dstep. I'd love it if I could import C headers directly.
Mar 18 2022