www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Intro to calling C libraries

reply Ian <ian iangarcia.net> writes:
Hi,

What is the recommended documentation or introductory material on 
how to call C libraries from D? I've seen it done in GtkD (for 
GTK3) and I have heard of -betterC, but it's all a little 
overwhelming. (I'm an experienced C programmer but new to D)

Cheers,
  Ian
Feb 20
next sibling parent reply Lance Bachmeier <no spam.net> writes:
On Thursday, 20 February 2025 at 20:09:29 UTC, Ian wrote:
 Hi,

 What is the recommended documentation or introductory material 
 on how to call C libraries from D? I've seen it done in GtkD 
 (for GTK3) and I have heard of -betterC, but it's all a little 
 overwhelming. (I'm an experienced C programmer but new to D)

 Cheers,
  Ian
Normally, you should be using ImportC. Look at the quick example from the spec: https://dlang.org/spec/importc.html#examples The first line of hello.c looks like this: ``` #include <stdio.h> ``` When ImportC compiles a C file, it runs the C preprocessor and does all the including you need. But rather than stdio.h, you can compile a C file that includes all the C headers you need. That's all you have to do. You can use the usual preprocessor calls like -I by using the -P switch: https://dlang.org/spec/importc.html#auto-cpp Assuming ImportC works with your C headers, that's everything you need. If ImportC doesn't work (as may be the case due to C extensions and preprocessor hacks), you should use dpp or dstep: https://dlang.org/spec/importc.html#dpp
Feb 20
parent reply Ian <ian iangarcia.net> writes:
On Thursday, 20 February 2025 at 21:05:40 UTC, Lance Bachmeier 
wrote:
 Normally, you should be using ImportC. Look at the quick 
 example from the spec: 
 https://dlang.org/spec/importc.html#examples

 The first line of hello.c looks like this:

 ```
 #include <stdio.h>
 ```

 When ImportC compiles a C file, it runs the C preprocessor and 
 does all the including you need. But rather than stdio.h, you 
 can compile a C file that includes all the C headers you need. 
 That's all you have to do. You can use the usual preprocessor 
 calls like -I by using the -P switch: 
 https://dlang.org/spec/importc.html#auto-cpp

 Assuming ImportC works with your C headers, that's everything 
 you need.
Perfect! I'll try this. Thank you.
Feb 20
parent reply Bradley Chatha <sealabjaster gmail.com> writes:
On Thursday, 20 February 2025 at 21:10:29 UTC, Ian wrote:
 ...
Another cool aspect of ImportC is that you can use the D compiler's header generator to generate .di files from C sources - i.e. semi-automatic, native binding generation! I say semi-automatic since it misses out things like macros, and unfortunately the header generator actually spits out invalid D code... e.g. I have a script [here](https://github.com/Juptune/juptune/blob/master/devops/scripts/ge -libsodium-di.bash) to generate bindings for libsodium.
Feb 23
parent Ian <ian iangarcia.net> writes:
Sweet!
Feb 24
prev sibling parent Dejan Lekic <dejan.lekic gmail.com> writes:
On Thursday, 20 February 2025 at 20:09:29 UTC, Ian wrote:
 What is the recommended documentation or introductory material 
 on how to call C libraries from D? I've seen it done in GtkD 
 (for GTK3) and I have heard of -betterC, but it's all a little 
 overwhelming. (I'm an experienced C programmer but new to D)
Ian, You do not need importC in order to interface with a C library. A good starting read would be: https://dlang.org/spec/interfaceToC.html If you know the C code (or C library you want to interface with) it is relatively easy to use it directly from D. The real challenge sometimes is to "port" complex C macros to D. The following page is an essential read: https://dlang.org/articles/ctod.html Here is a simple start project. Let's call liblz4's LZ4_versionNumber() function to get the version of the library, and print it out: ```d module lz4version; import std.stdio; // https://github.com/lz4/lz4/blob/dev/lib/lz4.h line 142 extern(C) int LZ4_versionNumber(); int main() { int lz4Version = LZ4_versionNumber(); int m = lz4Version / 10000; lz4Version = lz4Version % 10000; int n = lz4Version / 100; lz4Version = lz4Version % 100; int r = lz4Version; writeln("LZ4 library version: ", m, ".", n, ".",r); return 0; } ``` Save this code to the lz4version.d file, and let's compile and link to lz4version executable with: `gdc -o lz4version lz4version.d -llz4` Now, let's run it: ``` shell» ./lz4version LZ4 library version: 1.9.4 ``` Indeed that is the version of the LZ4 library I have on my local Fedora 40 workstation: `/usr/lib64/liblz4.so.1.9.4`
Feb 23