On 9/13/20 12:55 PM, James Blachly wrote:
Summary:
Can a typesafe D variadic function, or D variadic template pass its
parameters to a C variadic function?
Background:
I maintain a library binding [0] 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[0]))
{
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" [1])
Question:
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.
-Steve