4

my problem with vsprintf is that I can not obtain input arguments directly, I have to first get inputs one by one and save them in void**, then pass this void** to vsprintf(), it is all fine for windows, but when I come to 64bit linux, gcc cannot compile because it is not allowed to convert from void** to va_list, Is there anyone can give me some help how I should do under linux?

part of my code is:

void getInputArgs(char* str, char* format, ...)
{
    va_list args;
    va_start(args, format);
    vsprintf(str, format, args);
    va_end(args);
}  

void process(void)
{
    char s[256];
    double tempValue;
    char * tempString = NULL;
    void ** args_ptr =NULL;
    ArgFormatType format;   //defined in the lib I used in the code
    int numOfArgs = GetNumInputArgs();  // library func used in my code

    if(numOfArgs>1)
    {
        args_ptr = (void**) malloc(sizeof(char)*(numOfArgs-1));
        for(i=2; i<numOfArgs; i++)
        {
            format = GetArgType();    //library funcs

            switch(format)
            {
                case ArgType_double:
                    CopyInDoubleArg(i, TRUE, &tempValue);   //lib func
                    args_ptr[i-2] = (void*) (int)tempValue;    
                    break;

                case ArgType_char:
                    args_ptr[i-2]=NULL;
                    AllocInCharArg(i, TRUE, &tempString);  //lib func
                    args_ptr[i-2]= tempString;
                break;
            }
        }
    }

    getInputArgs(s, formatString, (va_list) args_ptr);   /////Here is the location where gcc cannot compile 
}

Many Many thanks!!

Philip Kendall
  • 4,304
  • 1
  • 23
  • 42
user1558064
  • 867
  • 3
  • 12
  • 28
  • Comment: if you're writing C rather than C++, you shouldn't type-cast the result of `malloc()`. Also, `sizeof(char)` is defined to be 1, so there's no need to have that. – Philip Kendall Jul 27 '12 at 15:47

1 Answers1

1

The problem is, your function gets ..., but you are passing it a va_list. ... is used for a usage like this:

 getInputArgs(s, formatString, arg1, arg2, arg3, arg4 /* etc */);

and it won't work with va_list. Unfortunately, there is not an easy way to create a va_list from different parameters instead of getting it from .... See this question for example.

What you should do is to change the way you want to print to the string.

You can have:

char s[256];
int so_far = 0;

And in your for loop instead of something like this:

CopyInDoubleArg(i, TRUE, &tempValue);   //lib func
args_ptr[i-2] = (void*) (int)tempValue;

You write:

CopyInDoubleArg(i, TRUE, &tempValue);   //lib func
if (so_far < 256)  /* 256 is the maximum length of s */
    so_far += snprintf(s + so_far, 256 - so_far, "%lf", tempValue);

Something along these lines. This way, you create the string one by one, appending each element to the previous, instead of trying to make it all at once.

Community
  • 1
  • 1
Shahbaz
  • 46,337
  • 19
  • 116
  • 182
  • Thanks a lot for the reply. very helpful. I am trying this on my machine. Weird thing about snprintf (I tried sprintf too, the same) is : I gave so_far +=snprintf(s+so_far, 256-so_far, "d", (int)tempValue) for double type, and "c" in the func for char type. then when I print out s, I get : s is cccc ( I gave 4 %c as inputs) or I get s is dccc ( I gave %d %c %c %c as inputs) which I think s is set to be the same as "d" or "c" as the third arguments in snprintf func. Any Clue? Thanks! – user1558064 Jul 27 '12 at 16:57
  • Continuing... I tried to add all inputs into one string as mentioned above and gave the string as one input for getInputArgs(), say inputString is the string holding all inputs. getInputArgs(string, formatString, inputString) , but I didnot get the right inputs. I checked the arguments obtained using va_arg, not right. – user1558064 Jul 27 '12 at 18:04
  • With this method, you don't need the `getInputArgs` function anymore. The string that you create is what `getInputArgs` would have created in your original program. Due to problems with `...` and `va_args` I moved the string construction in `process` so that you wouldn't need `getInputArgs` anymore. – Shahbaz Jul 28 '12 at 00:43