Wrapping c variadic functions

simendsjo simendsjo at gmail.com
Thu Feb 23 11:37:18 PST 2012


On Thu, 23 Feb 2012 18:42:51 +0100, Artur Skawina <art.08.09 at gmail.com>  
wrote:

> On 02/23/12 11:35, simendsjo wrote:
>> Say i have a c function (didn't include first format argument for  
>> simplicity)
>>
>> void print(...);
>> I wrap it up:
>> extern(System) void print(...);
>>
>> And then I try to wrap it up in some safer D way:
>> void print(Args...)(Args args)
>> {
>>     print(args); // only the first argument is printed
>> }
>>
>> void print(...)
>> {
>>     print(_argptr); // no go either
>> }
>>
>> How am I supposed to do this? http://dlang.org/function.html#variadic  
>> doesn't make my any smarter.
>>
>
> You may want to check if a va_list based version of the C function is  
> available.
> Anyway, the above should work, with a valid C prototype; this works here:
> ------------------------------------------------------------------------------------------
> import std.string;
>
> extern (C) int printf(const char*, ...);
>
> int dp(A...)(A args) { return printf(args); }
>
> void main(string[] argv) {
>    dp(cast(char*)"%s\n", argv[0].toStringz);
>    dp(cast(char*)"%s, %s\n", argv[0].toStringz, argv[1].toStringz);
>    dp(cast(char*)"%s, %s, %s\n", argv[0].toStringz, argv[1].toStringz,  
> argv[2].toStringz);
>    dp(cast(char*)"%s, %d, %s\n", argv[0].toStringz, 42,  
> argv[2].toStringz);
> }
> ------------------------------------------------------------------------------------------
>
> and you can even do things like:
>
> ------------------------------------------------------------------------------------------
> import std.string;
> import std.typetuple;
>
> extern (C) int printf(const char*, ...);
>
> int dp(A...)(A args) {
>    alias ReplaceAll!(immutable(char)[], char*, A) CA;
>    CA cargs;
>    foreach (i, arg; args) {
>       static if (is(typeof(arg):const(char)[]))
>          cargs[i] = cast(char*)arg.toStringz;
>       else
>          cargs[i] = arg;
>    }
>    return printf(cargs);
> }
>
> void main(string[] argv) {
>    dp("%s\n", argv[0]);
>    dp("%s, %s\n", argv[0], argv[1]);
>    dp("%s, %s, %s\n", argv[0], argv[1], argv[2]);
>    dp("%s, %d, %s\n", argv[0], 42, argv[2]);
> }
> ------------------------------------------------------------------------------------------
>
> to expose a more sane API.
>
> Note: this example only handles D strings.
>
> BTW, is there a simpler and/or more generic way to achieve this?  
> Thinking about
> using it in C bindings...
>
> artur

Hmm. Didn't my previous post make it to the newsgroup? Is visible at my  
end.
I wrote: "
My bad. The first version works just fine. I passed a float and had the  
format string as %d..."

So
print(Args...)(Args args)
{
   c_print(args); // works just fine
}


More information about the Digitalmars-d-learn mailing list