www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Wrapping c variadic functions

reply simendsjo <simendsjo gmail.com> writes:
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.
Feb 23 2012
next sibling parent simendsjo <simendsjo gmail.com> writes:
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...
Feb 23 2012
prev sibling next sibling parent James Miller <james aatch.net> writes:
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)
 {
 =C2=A0 =C2=A0print(args); // only the first argument is printed
 }

 void print(...)
 {
 =C2=A0 =C2=A0print(_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...
Feb 23 2012
prev sibling next sibling parent reply Artur Skawina <art.08.09 gmail.com> writes:
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
Feb 23 2012
parent Artur Skawina <art.08.09 gmail.com> writes:
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
Feb 23 2012
prev sibling next sibling parent simendsjo <simendsjo gmail.com> writes:
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 }
Feb 23 2012
prev sibling next sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
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
Feb 23 2012
prev sibling parent Brad Roberts <braddr puremagic.com> writes:
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.
Feb 23 2012