ImportC Rox

Don Allen donaldcallen at gmail.com
Wed Nov 9 15:00:39 UTC 2022


On Monday, 7 November 2022 at 22:05:38 UTC, Walter Bright wrote:
> https://news.ycombinator.com/item?id=33509223

The main application in the suite of financial tools I built for 
myself and ported to D from C uses the gtk3 and sqlite3 C 
libraries. Let's talk about gtk, which is a big system and has 
many convoluted and complex header files.

I dealt with gtk in my D code as you might expect. I created a 
gtk.d with hand-coded definitions and function prototypes such as
````
alias gconstpointer = immutable(void) *;

struct GtkWindow; // All structs that are dealt with by pointer 
only are defined this way

struct GtkTreeIter {
     long[4] dontcare;
} /* A few structs like this need to be stack-allocated in D 
code, their addresses
      passed to gtk functions. I check their sizes against globals 
containing
      sizeofs in a the lone C file that is part of this 
application */

extern (C) void gtk_tree_selection_select_iter(GtkTreeSelection* 
selection, GtkTreeIter* iter);
````
This is the standard pre-ImportC approach. Messy and ugly, but it 
works. However, if the library functions and C header files 
change, the application will break in unpredictable and 
hard-to-debug ways. At the moment, I'm using gtk3, which will not 
change because they've moved on to gtk4 with a somewhat different 
API. But if I decide to update to gtk4, I would be subject to 
this risk using this method.

I read the ImportC documentation when it first became available 
and several times since. I did not come away from those readings 
with a clear idea of how to use it to rid myself of the above. 
Then I saw Walter's comment in the link above. Aha -- you can 
just import header files in D code! The documentation does not 
say that, unless I've missed something. I think the relevant 
section is 41.3.2, which, given 'import hello', says "which will, 
if hello is not a D file, and has an extension .i or .c, compile 
hello with ImportC". No mention of .h files. Walter's comment 
made two things clear -- how to use ImportC in my case and that 
the documentation needs to be corrected and improved with an 
example of importing a C header file. Importing header files so 
you can directly use C libraries is a major reason why ImportC is 
an important addition to D and it should be crystal clear in the 
documentation how to do it.

With my improved understanding, I decided to give ImportC a try. 
All my D source files already had 'import gtk' statements, to get 
at my hand-coded definitions above. So no change was needed, 
since the goal was now to import gtk.h. I simply changed my 
makefile for this application to, in the invocations of dmd that 
compile my D source files, include the standard pkg-conf call 
that expands primarily into '-I's, indicating where to find all 
the gtk header files. A little post-processing of that expansion 
was necessary with sed, because dmd expects -I in a slightly 
different format than clang. I also needed to remove a couple of 
switches that dmd doesn't support.

I also removed the checks on struct sizes (and their definitions 
in my C file), since the struct definitions are now available 
directly from the Gtk header files.

Then I got rid of all references in the makefile to my gtk.d 
source file. After a few false starts due to things I overlooked, 
the application built successfully. This all took less than an 
hour. I've done some cursory testing and it seems to work 
properly. I was quite amazed at how easy this was.

So based on my initial experience, Walter's statement about 
ImportC's usefulness seems to be correct (I will report if 
anything turns up in more thorough testing) and I congratulate 
him for this work; it really facilitates the use of C libraries. 
I think this should be prominent in any "Why D?" presentation or 
discussion, because ImportC greatly enhances D's competitive 
position, in my opinion. Marketing!

I will add that I've played with zig a bit, starting a couple of 
years ago, attracted by its translate-c capability, which is 
analogous to ImportC. At that time, I remember looking at D as a 
candidate for the work I wanted to do and being put off by the 
realization that to use it, I would need to do something like the 
above hackery. I did eventually come back to D despite this, 
because Zig was and is not ready and because of my misadventures 
with Rust, which I've already discussed in other posts.


More information about the Digitalmars-d mailing list