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