Call C variadic function from D variadic function
schveiguy at gmail.com
Sun Sep 13 17:23:42 UTC 2020
On 9/13/20 12:55 PM, James Blachly wrote:
> Can a typesafe D variadic function, or D variadic template pass its
> parameters to a C variadic function?
> I maintain a library binding  to htslib, a high-performance and very
> widely used C library for high-throughput sequencing (hts) data files.
> We use this internally and haven't polished it for a release on the
> announce forum or biomed twitter, etc. yet.
> In the course of upgrading it to support the latest API/ABI (htslib-1.10
> / so.3), I need to add support for several new functions.
> One of these is a variadic function with the signature:
> `int sam_hdr_add_line(sam_hdr_t *h, const char *type, ...);`
> Of course, we can call this directly from D with hardcoded parameters.
> However, one of the focuses of our library is "bindings + wrappers" to
> make this feel more like native D. Thus, we want a variadic function to
> which we may pass D strings (it is also a struct member function).
> With help from Herringway on IRC, we came up with a solution using mixin:
> /// Add a single line to an existing header
> auto addLine(T...)(RecordType type, T kvargs)
> if(kvargs.length > 0 && isSomeString!(T))
> static assert (kvargs.length %2 == 0); // K-V pairs => even
> number of variadic args
> string varargMagic(size_t len)
> string args = "sam_hdr_add_line(this.h, type.ptr, ";
> for(int i=0; i<len; i++)
> args ~= "toStringz(kvargs[" ~ i.to!string ~ "]), ";
> args ~= "null)";
> return args;
> return mixin(varargMagic(kvargs.length));
> Interestingly, compilation fails if the mixin consists only of the
> comma-separated parameters ("Comma expression" )
> If a variadic template, despite presenting to the user a "dynamic
> array", MUST know its parameter list at compile-time, is there a way
> (other than with mixins as shown) to pass this parameter list to
> extern(C) linkage function with variadic parameters?
Was just talking about this exact problem with Adam Ruppe.
Unfortunately, because the parameters are an expression tuple, and not a
compile-time tuple, you can't use stuff like staticMap.
Manu's ... dip would be perfect for this:
return sam_hdr_add_line(this.h, this.ptr, toStringz(kvargs)..., null);
I think the only way it works today is if you use the mixin technique.
More information about the Digitalmars-d-learn