Thread overview
Wrapping c variadic functions
Feb 23, 2012
simendsjo
Feb 23, 2012
simendsjo
Feb 23, 2012
James Miller
Feb 23, 2012
Artur Skawina
Feb 23, 2012
simendsjo
Feb 23, 2012
Artur Skawina
Feb 23, 2012
H. S. Teoh
Feb 23, 2012
Brad Roberts
February 23, 2012
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.
February 23, 2012
On Thu, 23 Feb 2012 11:35:32 +0100, simendsjo <simendsjo@gmail.com> 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.

My bad. The first version works just fine. I passed a float and had the format string as %d...
February 23, 2012
On 23 February 2012 23:35, simendsjo <simendsjo@gmail.com> 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.

I'm pretty sure that std.c.stdarg is where you want to go, unfortunately, due to the fact that C varargs is a bit of black magic, you can only really wrap functions that provide v* versions. On top of that, std.c.stdarg is just a wrapper for the C library of the same name, so it doesn't provide a proper way to convert anything to a va_list.

However, if you experiment with v* functions from C, then you might be able to trick it...
February 23, 2012
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
February 23, 2012
On Thu, 23 Feb 2012 18:42:51 +0100, Artur Skawina <art.08.09@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
}
February 23, 2012
On 02/23/12 20:37, simendsjo wrote:
> Hmm. Didn't my previous post make it to the newsgroup? Is visible at my end.

The mailing list gets stuck sometimes and does not forward messages for hours. Your question made it, but the later post only arrived here minutes ago...

artur
February 23, 2012
On Thu, Feb 23, 2012 at 08:53:00PM +0100, Artur Skawina wrote:
> On 02/23/12 20:37, simendsjo wrote:
> > Hmm. Didn't my previous post make it to the newsgroup? Is visible at my end.
> 
> The mailing list gets stuck sometimes and does not forward messages for hours.  Your question made it, but the later post only arrived here minutes ago...

My MX was getting Disk Full errors from the primary SMTP server. Probably traffic on D mailing lists is too high for the mailing list to handle. :)


T

-- 
Computerese Irregular Verb Conjugation: I have preferences.  You have biases.  He/She has prejudices. -- Gene Wirchenko
February 23, 2012
On Thu, 23 Feb 2012, H. S. Teoh wrote:

> On Thu, Feb 23, 2012 at 08:53:00PM +0100, Artur Skawina wrote:
> > On 02/23/12 20:37, simendsjo wrote:
> > > Hmm. Didn't my previous post make it to the newsgroup? Is visible at my end.
> > 
> > The mailing list gets stuck sometimes and does not forward messages for hours.  Your question made it, but the later post only arrived here minutes ago...
> 
> My MX was getting Disk Full errors from the primary SMTP server. Probably traffic on D mailing lists is too high for the mailing list to handle. :)

The interruptions to mail flow have actually been driven by the auto-tester filling up the disks periodically.  I'm going to have to separate the tester off onto a different box to avoid the problem I think. Anyway, sorry for the interruption.