I am translating 3rd party library API written in C to D. That library exports a lot of functions named like libname_foofunc
, libname_barfunc
etc., which is expectable for C library to prevent bloating global namespace. As D is more modular than C, I want to provide more D'ish interface and get rid of function prefix, so functions will look like libname.c.foofunc
and libname.c.barfunc
.
As library is unaware of my "improvements", I have to somehow translate libname.c.foofunc
into libname_foofunc
and preserve correct extern-linkage, destination name mangling and calling convention at the same time.
Assuming there is way (which I don't know either) to tell linker that external unresolved symbol __imp__D1c7foofuncFZi
corresponds to _libname_foofunc
or libname_foofunc@0
(despite the fact I have to do name mangling by hands), there is still problem telling D what calling convention is.
In case I explicitly specify extern(C) int foofunc()
in libname/c.di
, there is no longer calling convention problem, but name gets translated to _foofunc
, which also differs from expected.
So, is there way in D to import foreign function under different name than it was exported?
I've though about importing functions "as is" under their original names and then alias-ing them to prefixless analogues, but this seems to be quite clumsy.
As far as linking goes, symbols are really a C thing, since we're talking about the C linker. D's situation with linking and exported symbols is basically the same as it is in C++, which is why there are mangled names and the like. You're going to have to create declarations for them in D using their original names, because that's what the linker is going to expect. D doesn't do anything different or magical which would change that. There are only two ways that you're going to be able to use different names.
alias the functions in your D code. You can just put the aliases in whatever module lists the symbols (since you have to declare them in D anyway). Then your code could use either the original names or the aliases. I don't see anything clumsy about that.
Create wrapper functions - either in C or D - and have your D code use those.
The aliases would definitely be better IMHO. They don't introduce any overhead and are less complicated.
But regardless, the normal thing to do when using C libraries from D is just to use the C function names. You're calling C functions, and that fact shouldn't be hidden. They're not D functions and don't act the same (even if they're similar) - especially when it comes to stuff like who owns the memory of what you're passing to functions. The gain in renaming them is debatable. It's usually when a D wrapper is written to give an API a cleaner, more D-like API (and not just changing the names) that the C functions aren't used directly anymore. A good example of this in Phobos would be etc.c.curl vs std.net.curl. etc.c.curl is purely the C API and doesn't attempt to rename anything. It doesn't create any aliases to make the symbols match Phobos' naming conventions or make them more D-like. It's essentially just the D version of the curl's header files. std.net.curl, on the other hand, builds on top of it to provide a more D-like API and abstraction. It does far more than rename the C functions.