Results 1 to 8 of 8

Thread: Transform a QVector / QStringList in a va_list

  1. #1
    Join Date
    Apr 2013
    Location
    milan
    Posts
    13
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Transform a QVector / QStringList in a va_list

    Hy to all I have a GUI application that at work we use to test the creations of Qt Widget itself, for example I have a dialog to create a QMessageBox with favourited properties icon, title, message and button of Qt or custom (you write the text on a list).

    All this data are send using a json and the buttons are memorized in QStringList, I have a C function that creates the json, that normally it would called in C but now I want to call in C++, but how convert the QStringList in the “…” (va_list de facto?).

    This is the prototype of the function that I want use:

    Qt Code:
    1. void messagebox(json_object **json, char *iconType, char *title, char *msg, int showTime, ...
    2. /* char *btn1, char *btn2, ... */ );
    To copy to clipboard, switch view to plain text mode 

    I cannot change the signature of the function to use a QStringList as it have to be used by a plain C application…

    I have found a solution that in Windows XP works, but, obviously is not really portable:

    Qt Code:
    1. void foo(int n, va_list args)
    2. {
    3. int i = 0;
    4.  
    5. printf("[foo] n is %d and i is %d\n", n, i);
    6.  
    7. for (; i != n; ++i)
    8. printf("'%s'\n", va_arg(args, char *));
    9.  
    10. printf("I'm here... safe!\n");
    11. }
    12.  
    13. int main(int argc, char *argv[])
    14. {
    15. QCoreApplication a(argc, argv);
    16.  
    17. QStringList args = a.arguments();
    18.  
    19. QVector<char *> v;
    20.  
    21. // It works but I need to allocate memory as QString::toAscii().data() is not saved in 'v' I don' know why!
    22. foreach (QString a, args) {
    23. //char str[strlen(a.toAscii().data()) + 1];
    24. char *str = strdup(a.toAscii().data());
    25.  
    26. //strcpy(str, a.toAscii().data());
    27. printf("adding to v: '%s'\n", a.toAscii().data());
    28. v << str;
    29. }
    30.  
    31. foo(args.count(), reinterpret_cast<va_list>((v.data())));
    32.  
    33. // Now I need to free() str in v or not? If it was a real function and not main() I has a memory leak here or not?
    34. return 0;
    35. }
    To copy to clipboard, switch view to plain text mode 

    As you could see it is a Kludge it incredibly works as, at least in Windows and Linux/X86, va_list is, in reality a char *. So I pass all the strings one after another to the “foo” function…

    At least I’d like to use a vector of QString to avoid the allocation of memory but I cannot find a way, data() in this case would be what a QString? Or QString *? Or a QString[]? The toAscii().data() seems to not create a valid QByteArray...

    By the way if my PM see that code probably he will kill me so I’m asking to you there’s a more portable solution in Qt to this problem?

    For example supposing that could be happy with max 32 buttons MOC could automate the scripture of code as this:

    QStringList buttons;

    switch(buttons) {
    case 0: // We have no buttons so I could call messagebox() w/o the last arg
    messagebox(json_object **json, char *iconType, char *title, char *msg, int showTime);
    break;

    case 1: // We have only one buttons simple is the first element of the list...
    messagebox(json_object **json, char *iconType, char *title, char *msg, int showTime, buttons[0]);
    break;

    case 2: /* 2 buttons they're in index 0 and 1 */
    messagebox(json_object **json, char *iconType, char *title, char *msg, int showTime, buttons[0], buttons[1]);
    break;
    .... /* 3-4-5-6-7-... buttons */
    case 31:
    messagebox(json_object **json, char *iconType, char *title, char *msg, int showTime, buttons[0], buttons[1], buttons[2], buttons[3], buttons[4], buttons[5], [...], buttons[31]);
    break;
    }
    What do you think? Is this possible?

    Thanks for your attention…

    P.S. For the de-allocation of the char * I've resolved calling QdeleteAll() on the QVector and then his method clean()... I've seen another useful class call QScopedPointer but the compiler doesn't liked the declaration of QVector < QScopedPointer > sadly

  2. #2
    Join Date
    Mar 2009
    Location
    Brisbane, Australia
    Posts
    7,729
    Thanks
    13
    Thanked 1,610 Times in 1,537 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows
    Wiki edits
    17

    Default Re: Transform a QVector / QStringList in a va_list

    Anything you do with va_list arguments is going to be a kludge and prone to breakage.

    If you cannot alter the interface of the existing function why not add another with a sane (less insane) interface:
    Qt Code:
    1. void messagebox(json_object **json, char *iconType, char *title, char *msg, int showTime, char **buttonNames);
    To copy to clipboard, switch view to plain text mode 
    To avoid repeating yourself you can change the implementation of the the va_list version to build a suitable list of strings for the new implementation. Your legacy C code keeps calling the va_list version and your new code uses the new interface.

    Incidentally, how does the existing C code call this function? Surely it faces exactly the same problem.

  3. #3
    Join Date
    Apr 2013
    Location
    milan
    Posts
    13
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Transform a QVector / QStringList in a va_list

    Quote Originally Posted by ChrisW67 View Post
    Anything you do with va_list arguments is going to be a kludge and prone to breakage.
    Sure the "solution" is a Kludge, yes, but strangely it seems partially portable the same code worked on Windows XP and Linux w/o problems... I cannot garantue it could work in other platform as Mac OSX or totally different CPU as ARM, Power PC...

    Quote Originally Posted by ChrisW67 View Post
    If you cannot alter the interface of the existing function why not add another with a sane (less insane) interface:
    Qt Code:
    1. void messagebox(json_object **json, char *iconType, char *title, char *msg, int showTime, char **buttonNames);
    To copy to clipboard, switch view to plain text mode 
    The function is indeed safe it seems to don't have a way to found when args end but in reality it has; it is declared as an always inline function using the GCC extensions __builtin_va_arg_pack() and more importantly __builtin_va_arg_len().

    The real function (that no one should call it directly!) is this:

    Qt Code:
    1. void messagebox_aux(json_object **json, char *iconType, char *title, char *msg, int showTime, [B]int n_buttons[/B], ...
    2. /* char *btn1, char *btn2, ... */ );
    To copy to clipboard, switch view to plain text mode 

    where n_buttons are the number of va_args calculated using the macro __builtin_va_arg_len().
    So I obtain a partial overloaded function in C as I could call it as:

    Qt Code:
    1. messagebox(&json, "alert", title, msg, showTime); // This an alert with it has no buttons
    To copy to clipboard, switch view to plain text mode 

    that translates to:
    Qt Code:
    1. messagebox_aux(&json, "alert", title, msg, showTime, 0); // no args and n_buttons is 0!
    To copy to clipboard, switch view to plain text mode 

    or as:

    Qt Code:
    1. messagebox(&json, "alert", title, msg, showTime, "OK"); // This an alert with only a button called "OK"
    To copy to clipboard, switch view to plain text mode 

    that translates to:
    Qt Code:
    1. messagebox_aux(&json, "alert", title, msg, showTime, 1, "OK"); // an arg so n_buttons is 1 and is called "OK"
    To copy to clipboard, switch view to plain text mode 

    Your version could solve the problem in Qt maybe but I need to create the array before calling the function, right?
    I think I could not do this:

    Qt Code:
    1. messagebox(&json, "alert", title, msg, showTime, {"OK", "Discard", "Cancel", "..."});
    To copy to clipboard, switch view to plain text mode 

    But I would have to do this:
    Qt Code:
    1. char *arr[] = {"OK", "Discard", "Cancel", "..."};
    2. messagebox(&json, "alert", title, msg, showTime, arr);
    To copy to clipboard, switch view to plain text mode 

    ... and I cannot call it w/o the last arg, right? It wouldn't compile...

    In any case in C I'm pretty sure cannot declare an array in a function declaration, right?

    Quote Originally Posted by ChrisW67 View Post
    To avoid repeating yourself you can change the implementation of the the va_list version to build a suitable list of strings for the new implementation. Your legacy C code keeps calling the va_list version and your new code uses the new interface.
    In the end yes I was forced to create a version that takes a va_list as this Kludge creates a va_list from a QVector not a "..." and it seems they have "forgotten" a method to pass from a va_list to a "..." there's only the other way around... so in the end the list of calls is this:

    Qt Code:
    1. always inline void messagebox(...);
    2. always inline void message_box_aux(...); // creates the va_list using the va_start() macro
    3. vmessagebox(json_object **json, char *iconType, char *title, char *msg, int showTime, int n_buttons, va_list buttons)
    To copy to clipboard, switch view to plain text mode 

    Quote Originally Posted by ChrisW67 View Post
    Incidentally, how does the existing C code call this function? Surely it faces exactly the same problem.
    The C code calls the first version and Qt calls the last one after the QVector -> va_list ugly hack... by the way I seem to have found a bug in the __bultin_va_arg_pack() thing as, for convenience, I have created other proxy functions to create the various types of MessageBox and they are always inline and use __bultin_va_arg_pack() in any call until they arrive to vmessagebox but n_buttons is always 0... when args are presents in the first function call, too! It seems to not work well if called too much times...

    I fear I'm forced to create MACROS but they are really unsafe as don't check the args types...

    Oh well if only I could use Qt / C++ for all my applications... plain C in 2013 is so limiting really...

    If I had to this in Qt/C++? I could create 3 methods using overloading:

    Qt Code:
    1. void messagebox(json_object **json, char *iconType, char *title, char *msg, int showTime);
    2. void messagebox(json_object **json, char *iconType, char *title, char *msg, int showTime, QString button);
    3. void messagebox(json_object **json, char *iconType, char *title, char *msg, int showTime, QStringList button);
    To copy to clipboard, switch view to plain text mode 

    all would be more easy, intuitive, without hacks or unportable GCC extensions... but my PM say "C++ is ugly and slow (?), our society write ANSI C... K&R and better if C90 compliant"!

    So annoying
    Last edited by fanoI; 19th April 2013 at 23:31.

  4. #4
    Join Date
    Sep 2011
    Posts
    1,241
    Thanks
    3
    Thanked 127 Times in 126 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Transform a QVector / QStringList in a va_list

    lol, second time in two days I see a C lover call C++ ugly! C++ is much prettier than C imo. va_list is inherently unsafe as there is no type checking, so you should not worry about the same issue in your macros. Generally this is a problem throughout C! Your PM sounds like a douche. If you are using Qt, then there is already a C++ 'bottleneck', so why stick to C?

    The best way is to expose
    Qt Code:
    1. void messagebox(json_object **json, char *iconType, char *title, char *msg, int showTime, va_list ap)
    To copy to clipboard, switch view to plain text mode 
    so that you can make your own va_list and pass into this method. Without this available, you only have hack solutions, I think.
    Last edited by amleto; 20th April 2013 at 13:01.
    If you have a problem, CUT and PASTE your code. Do not retype or simplify it. Give a COMPLETE and COMPILABLE example of your problem. Otherwise we are all guessing the problem from a fabrication where relevant details are often missing.

  5. #5
    Join Date
    Apr 2013
    Location
    milan
    Posts
    13
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Transform a QVector / QStringList in a va_list

    Quote Originally Posted by amleto View Post
    lol, second time in two days I see a C lover call C++ ugly! C++ is much prettier than C imo. va_list is inherently unsafe as there is no type checking, so you should not worry about the same issue in your macros. Generally this is a problem throughout C! Your PM sounds like a douche. If you are using Qt, then there is already a C++ 'bottleneck', so why stick to C?
    I think in the same way C++ is better than C overloading, inheritance, GUI toolkits (as our friend Qt), event driven programming... the only thing that C++ did wrong is, IMHO, that could be, for someone, one of its point of force the C compatibility why:

    1. All the pointers things are unsafe!
    2. The C compatibly is not complete, too... an essential C keyword called NULL is not present (it calls it "0"), and an empty variable doesn't evaluates to false
    3. Code that C compiles perfectly or giving only a warning doesn't compile in C++ !


    We maybe you could hate me but I, personally, prefer the Java approach all is object (well not completely to be honest int is primitive variable Int is the object), no pointer and no compatibility with the old, ugly (it is that beast that is ugly not Qt/C++) and unsafe C.

    By the way yes va_args are unsafe __builtin_va_arg_pack() tries to mitigate the problem as at least permits to check the size of the args without the need to use a variable or a NULL in the end but yes if I pass an int instead of char * the code would compile and, probably will crash when it will try to convert to a char *!

    In the end if I don't have done nothing wrong and there's a bug in __builtin_va_arg_pack() when called by a function that calls again __builtin_va_arg_pack() I go for a hibryd approach: I'll implement the info(), warning(), alert(), wait() as variadic macro that will call the messagebox function... but I hate the macro syntax in particular when I have to write functions like macros

    Quote Originally Posted by amleto View Post
    The best way is to expose
    Qt Code:
    1. void messagebox(json_object **json, char *iconType, char *title, char *msg, int showTime, va_list ap)
    To copy to clipboard, switch view to plain text mode 
    so that you can make your own va_list and pass into this method. Without this available, you only have hack solutions, I think.
    By the way the hack is in test code so not problem but the curiosity remains is possible to use the Meta Object Compiler to create your own code?
    I could use him to make a switch for example? Maybe in the future I could find a good usage of this technique...

  6. #6
    Join Date
    Sep 2011
    Posts
    1,241
    Thanks
    3
    Thanked 127 Times in 126 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Transform a QVector / QStringList in a va_list

    what would be the point in using moc to generate code? your problem is still a run-time problem, so moc can't help you there...
    If you have a problem, CUT and PASTE your code. Do not retype or simplify it. Give a COMPLETE and COMPILABLE example of your problem. Otherwise we are all guessing the problem from a fabrication where relevant details are often missing.

  7. #7
    Join Date
    Apr 2013
    Location
    milan
    Posts
    13
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Transform a QVector / QStringList in a va_list

    See my fist post I wanted MOC to help me to write at least the first 32 version of the switch()... is this possible?

    It is in general possible to make MOC create custom code?

  8. #8
    Join Date
    Sep 2011
    Posts
    1,241
    Thanks
    3
    Thanked 127 Times in 126 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Transform a QVector / QStringList in a va_list

    no, I don't think so. Just write it by hand - it's going to look ugly whether you do it or moc does it (if it could).
    If you have a problem, CUT and PASTE your code. Do not retype or simplify it. Give a COMPLETE and COMPILABLE example of your problem. Otherwise we are all guessing the problem from a fabrication where relevant details are often missing.

Similar Threads

  1. sort a Qvector based on another Qvector
    By OzQTNoob in forum Qt Programming
    Replies: 2
    Last Post: 16th February 2012, 06:39
  2. Replies: 5
    Last Post: 2nd September 2011, 23:11
  3. Need to create QStringList and QVector in FORTRAN
    By praveen in forum Qt Programming
    Replies: 4
    Last Post: 3rd April 2008, 15:20
  4. Bring va_list args; to a QStringList or a qmap
    By patrik08 in forum General Programming
    Replies: 8
    Last Post: 18th June 2006, 12:31
  5. Replies: 7
    Last Post: 2nd June 2006, 12:48

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.