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

Reply via email to