View mode: basic / threaded / horizontal-split · Log in · Help
February 23, 2012
Wrapping c variadic functions
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
Re: Wrapping c variadic functions
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
Re: Wrapping c variadic functions
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
Re: Wrapping c variadic functions
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
Re: Wrapping c variadic functions
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
Re: Wrapping c variadic functions
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
Re: Wrapping c variadic functions
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
Re: Wrapping c variadic functions
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.
Top | Discussion index | About this forum | D home