Call C variadic function from D variadic function

Steven Schveighoffer schveiguy at gmail.com
Sun Sep 13 17:23:42 UTC 2020


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


More information about the Digitalmars-d-learn mailing list