D and C APIs

Atila Neves via Digitalmars-d digitalmars-d at puremagic.com
Wed Jan 13 00:58:45 PST 2016


On Tuesday, 12 January 2016 at 14:10:02 UTC, John Colvin wrote:
> On Tuesday, 12 January 2016 at 13:24:48 UTC, Russel Winder 
> wrote:
>> On Tue, 2016-01-12 at 11:05 +0000, John Colvin via 
>> Digitalmars-d wrote:
>>> […]
>>> 
>>> What's so hard about writing a few function prototypes, 
>>> aliases and enums? It's annoying that we have to do it, but 
>>> compared to writing the rest of a project it's always going 
>>> to be a tiny amount of work.
>>
>> I started there but gave up quite quickly as there are two 
>> levels of API here, both of which are needed to use the 
>> higher-level API as it refers directly to low-level structs 
>> and stuff.
>>
>> There is the kernel device drivers level, which defines the 
>> low-level API, and then there is libdvd5 which provides a 
>> (slightly) higher C API – with all the idiocies of a C API for 
>> doing high-level library programming :-(
>>
>> I have found a Rust wrapper of the kernel API, but that would 
>> mean writing all the libdvbv5 equivalent myself before writing 
>> the application code. There is no equivalent D version and 
>> certainly no easy way of wrapping libdvbv5 in D without it. Go 
>> has problems with C APIs and no sensible GTK3 wrapper.
>>
>>> For a lot of projects you can only bind what you actually 
>>> need, I often just pretend that I have already written the 
>>> bindings then write whatever lines are necessary to get it to 
>>> compile!
>>
>> The problem is that this is easy in C++ for a C API, but not 
>> for D or Rust using the same C API. C++ can use the C stuff 
>> directly, D and Rust need an adaptor.
>
> I agree it's easier in C++, but what I mean is literally doing 
> something like:
>
> 1) write code pretending you've got complete bindings
> 2) try to compile
> 3) write the bare minimum bindings necessary to make it compile
> 4) goto 1
>
> It's amazing how little of an API often ends up being used and 
> therefore how little binding code you have to write.
>
> Alternatively you can write the bindings immediately when you 
> use them, but I prefer not having to do the context switch 
> between writing application and bindings quite as often as that.

It's a nice technique that I hadn't thought about, and I'll 
definitely try it.

I won't always work, though. At work we write our own operating 
systems with loooooads of platform headers. Every function 
definition depends on struct definitions that are in other 
headers which are generated from macros that.... you get the 
point.

Unless, of course, I give up on accessing struct members from D, 
pass everything as void* and write C accessors. Which is a pain, 
especially compared to:

extern "C" {
#include "foo.h"
#include "bar.h"
}

Atila



More information about the Digitalmars-d mailing list