10 years, 8 months ago.

RPCFunction syntax example?

I have RPCVariable working OK but don't seem to be able to work out the correct syntax to even compile with a call to the RPCFunction routine. I'm a bit new to c++ so what is wrong with the following and does anyone have a working example?

void doGetData(char * input, char * output);
RPCFunction getData(&doGetData, "getData");
void doGetData(char * input, char * output) { 

    ... etc
}

The error is:
No instance of constructor "mbed::RPCFunction::RPCFunction" matches the argument list.

Thanks for your help
David

Question relating to:

1 Answer

10 years, 8 months ago.

I am getting exactly the same error as David. This syntax had worked previously but seems to now be broken for some reason. Thanks, Louis

Accepted Answer

Hello guys,

could you share more details? I glanced over RPC functions, the constructor of official RPC from mbed has following declaration:

RPCFunction(void (*f)(Arguments*, Reply*), const char* = NULL);

I checked the history of those files, that constructor has always been there declared as it is at the moment.

Which is obviously different than yours doGetData(char*, char*). In addition, there is rpc library from a user Michael Walker, which uses the following:

RPCFunction(void(*f)(char*, char*), const char* = NULL);

Which one do you include in your project?

Regards,
0xc0170

posted by Martin Kojtal 15 Aug 2013

Martin, I am using both the th mbed_rpc and Michael Walker's RPCInterface. I included the mbed_rpc because the rpc.h file is not included in Walkers library for some reason but yet is referenced from his code. Should I not include both of these libraries? I think my use of the RPCFunction declaration is consistent with Mr. Walkers format and yet I get the same error message as David did. My calls are basically just a 'pointer for a function with two arguments both char pointers and that returns a void' this is the same as Mr. Walkers '

RPCFunction(void(*f)(char*, char*), const char* = NULL)"

The error message is: "No instance of constructor "mbed::RPCFunction::RPCFunction" matches the argument list" in file "/main.cpp" Possibly my problem is that I should not be including the Mbed_rpc library along with the RPCInterface since they both define the RPCFunction interface.

Thanks for your response, Louis Ashford

My code looks like the following:

Function prototype void getTesterStatus(char *input, char * Output);

RPCFunction Declaration RPCFunction GetTesterStatus(&getTesterStatus, "GetTesterStatus");

/*

  • Get Tester Status
  • / void getTesterStatus(char *input, char * Output){ switch (TesterStatus) { < TesterStatus is a global set in another place case IDLE: sprintf(Output, "%s", "IDLE"); break; case RUN: sprintf(Output, "%s", "RUNNING"); break; case STOPPED: sprintf(Output, "%s", "STOPPED"); break; case ERROR: sprintf(Output, "%s", "ERROR"); break; default: break; } }
posted by Louis Ashford 15 Aug 2013

Hi Martin,

Thanks for the reply. I originally wrote the above code based on an example from Michael Walker’s project but have only included the more recent official mbed-rpc library. For some reason I was interpreting “Arguments” and “Reply” as parameter names, still thinking they were pointers to character strings. Your comment makes me realise they aren’t and I found the definitions in Arguments.h . However, I’m new to c++ and the syntax is still defeating me, so will have to do some more reading. If you know of an example that works with the official mbed-rpc library, then that would probably help clarify it for me.

Regards David.

posted by David Pairman 15 Aug 2013

David, I was able to get passed this error by redefining my function arguments to be of type Arguments and Reply as in the mbeb RPCFunction prototype. So my call now looks like this:

void getTestStatus(Arguments *input, Reply * Output);

RPCFunction GetTesterStatus(&getTestStatus, "GetTestStatus");

That fixes this error at least and I am now on to the next error in my code which is something else.. "there is always something else" Hope this fixes your problem as well.. Thanks, Louis

posted by Louis Ashford 15 Aug 2013

Thanks Louis.

In fact I made that exact change immediately I realised my stupidity from Martin’s answer and before writing my last comment. However, as you say, there is always something else… and I was stumped on how the declarations in Arguments.h were intended to be used as there is no documentation. After examining the code and reading a bit more on classes I think I understand it now.

The constructor for the Arguments class has already parsed the received string down into a set of strings; obj_name, method_name, and an argv array of char*. It also sets the argument counter argc. A set of template functions, “getArg”, are available to return the arguments as the type expected. I’m not sure what happens if the input string does not match the types expected.

The Reply class is similar in that it uses a set of template functions, “putData”, to generate the return string. Parameters are separated by a space character. Unfortunately there is no control over the formatting so I will probably format parameters to strings first.

I think the following will illustrate it;

void doGetData(Arguments* input, Reply* output);
RPCFunction getData(&doGetData, "getData");

void doGetData(Arguments* input, Reply* output) {
    // Arguments are already parsed into argv array of char*
    printf("Object name = %s\n",input->obj_name);
    printf("Method name = %s\n",input->method_name);
    for (int i=0; i < input->argc; i++)
        printf("argv[%1d] = %s \n",i,input->argv[i]);
        
    // Alternatively the arguments can be recovered as the types expected
    // by repeated calls to getArg()
    int arg0 = input->getArg<int>();                      // Expecting argv[0] to be int
    printf("Expecting argv[0] to be int = %d\n",arg0);
    float arg1 = input->getArg<float>();                  // Expecting argv[1] to be float
    printf("Expecting argv[1] to be float = %f\n",arg1);
    const char *arg2 = input->getArg<const char*>();      // Expecting argv[2] to be a string
    printf("Expecting argv[2] to be a string = %s\n",arg2);

    // The output parameter string is generated by calls to putData, which separates them with spaces.
    output->putData(arg0);
    output->putData(arg1);
    output->putData(arg2);
}


My mbed has IP address 192.168.1.189, so if I send the following from a browser via the Ethernet:
http://192.168.1.189/rpc/getData/run 45 3.6 test
I will get the following output on the mbed terminal

Object name = getData
Method name = run
argv[0] = 45
argv[1] = 3.6
argv[2] = test
Expecting argv[0] to be int = 45
Expecting argv[1] to be float = 3.600000
Expecting argv[2] to be a string = test


And the following returned to the browser

45 3.5999999046325684 test
posted by David Pairman 16 Aug 2013

David, Thank you for your response. Yes I also found the same. I was previously parsing the argument strings passed to my RPC functions in the functions and had made them specific to the function however this does simplify that some so I understand why they did that. Thanks again for taking time to assist. Louis

posted by Louis Ashford 19 Aug 2013