digitalmars.D.learn - forward variadic arguments
- Frank Benoit (6/6) Jun 15 2006 void execSql( char[] aSql, ... ){
- Deewiant (10/18) Jun 15 2006 You'll need to do it "manually" by calling the std.format.doFormat funct...
- Frank Benoit (6/16) Jun 15 2006 And what happend to my format string 'aSql' ? :)
- Deewiant (22/41) Jun 15 2006 Oh, whoops! :-)
- Tom S (38/45) Jun 15 2006 I know it's evil and stuff, but I had to do this :D
- Daniel Keep (13/26) Jun 16 2006 One of the projects I've been thinking about doing is writing a library
void execSql( char[] aSql, ... ){ char[] sql = std.string.format( aSql, _arguments, _argptr ); database.exec( sql ); } The forwarding of all arguments to format() seams not to work. how can I do this?
Jun 15 2006
Frank Benoit wrote:void execSql( char[] aSql, ... ){ char[] sql = std.string.format( aSql, _arguments, _argptr ); database.exec( sql ); } The forwarding of all arguments to format() seams not to work. how can I do this?You'll need to do it "manually" by calling the std.format.doFormat function. void execSql(char[] aSql, ...) { char[] sql; void putc(dchar c) { sql ~= c; } std.format.doFormat(&putc, _arguments, _argptr); database.exec(sql); }
Jun 15 2006
void execSql(char[] aSql, ...) { char[] sql; void putc(dchar c) { sql ~= c; } std.format.doFormat(&putc, _arguments, _argptr); database.exec(sql); }And what happend to my format string 'aSql' ? :) TypeInfo[] ti; ti ~= aSql.typeinfo; ti ~= _arguments void* p = ????; std.format.doFormat(&putc, ti, p);
Jun 15 2006
Frank Benoit wrote:Oh, whoops! :-) I guess you could try a hack like that. I think you'll have to use std.stdarg - somehow; I've never done this myself - to collect the arguments themselves into an array and then pass the address of the first element of that array as the equivalent of _argptr. BTW, "aSql.typeinfo" is deprecated: use "typeid(typeof(aSql))" or just "typeid(char[])" if you're confident you'll never change its type. Personally, I'd just change the function signature to "void execSql(...)". It gives a bit more versatility, the following are equivalent: execSql("%d hello %d", a, b); execSql(a, " hello ", b); execSql("%d hello ", a, b); If you really want to force the first parameter to be char[], I think the only way to be sure (apart from that hackish approach, of course :-P) is to assert it at runtime: void execSql(...) in { assert (_arguments[0] == typeid(char[])); } body { // the code }void execSql(char[] aSql, ...) { char[] sql; void putc(dchar c) { sql ~= c; } std.format.doFormat(&putc, _arguments, _argptr); database.exec(sql); }And what happend to my format string 'aSql' ? :) TypeInfo[] ti; ti ~= aSql.typeinfo; ti ~= _arguments void* p = ????; std.format.doFormat(&putc, ti, p);
Jun 15 2006
Frank Benoit wrote:void execSql( char[] aSql, ... ){ char[] sql = std.string.format( aSql, _arguments, _argptr ); database.exec( sql ); } The forwarding of all arguments to format() seams not to work. how can I do this?I know it's evil and stuff, but I had to do this :D import std.stdio; /** there's a simpler solution, actually, but it makes the assumption, that _argptr - xsize == &x; without exploiting this assumption, the following code should even be portable ;D */ void foo(char[] x, ...) { TypeInfo[] args = _arguments.dup; void* ptr = _argptr; const size_t xsize = (char[]).sizeof; ubyte[xsize] ptrVal = (cast(ubyte*)ptr)[0 .. xsize]; // we'll be writing to the stack, this array will store the old values ubyte[xsize] backup; // this will hold the binary contents of 'x' ubyte[xsize] newVal; // make space for the value we'll be inserting to the stack ptr -= xsize; // it will tell writefx to expect another argument args = typeid(char[]) ~ args; // make a backup of the old value of ptrVal backup[] = ptrVal[]; // and get the new values into the temp array newVal[] = (cast(ubyte*)&x)[0 .. xsize]; // finally, write the new values ptrVal[] = newVal[]; writefx(stdout, args, ptr, true); // restore the old stack data ptrVal[] = backup[]; } void main() { foo("foo ", "bar", 1, 2, 3); } -- Tomasz Stachowiak /+ a.k.a. h3r3tic +/
Jun 15 2006
Tom S wrote:Frank Benoit wrote:One of the projects I've been thinking about doing is writing a library for doing programmatic function calls, which would allow things like this to actually be portable :P Of course, I've been putting it off since Walter still hasn't documented the calling convention for D, and I didn't even realize until a month or so ago that it (sometimes) passes an argument in EAX >_< -- Daniel -- Unlike Knuth, I have neither proven or tried the above; it may not even make sense. v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP http://hackerkey.com/void execSql( char[] aSql, ... ){ char[] sql = std.string.format( aSql, _arguments, _argptr ); database.exec( sql ); } The forwarding of all arguments to format() seams not to work. how can I do this?I know it's evil and stuff, but I had to do this :D [snip evil but quite handy code]
Jun 16 2006