Call C variadic function from D variadic function
Steven Schveighoffer
schveiguy at gmail.com
Sun Sep 13 19:16:48 UTC 2020
On 9/13/20 2:35 PM, Paul Backus wrote:
> On Sunday, 13 September 2020 at 17:23:42 UTC, Steven Schveighoffer wrote:
>> On 9/13/20 12:55 PM, James Blachly wrote:
>>>
>>> ```
>>> /// 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.
>
> You actually can, if you define the right kind of helper function:
>
> /// 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
> immtuable(char)* argToStringz(alias arg)()
> {
> return toStringz(arg);
> }
>
> return sam_hdr_add_line(this.h, this.ptr,
> staticMap!(argToStringz, kvargs), null);
> }
>
> The clever trick here is that, because of optional parentheses [1],
> `argToStringz!(kvargs[i])` can be interpreted either as the name of a
> function or a function call, depending on the context it appears in.
That's cool. And horrific at the same time :) I mean the templates that
you have to instantiate for this...
I would prefer the mixin solution, even though it's uglier. I think
something that abstracts that out would be a nice thing to have for
std.meta.
-Steve
More information about the Digitalmars-d-learn
mailing list