Okay. Now I changed my rpc params to transferable types. I am using Rpc_in_buffer<> instead of std::string. I want to receive a feedback message from a server through an Rpc_in_buffer<> argument, but the client doesn't receive the results from the server correctly while working correclty with an character array.
I should not use Rpc_in_buffer for a reply message from a server?
I added test codes to the hello_tutorials : ------ include/hello_session/client.h---- typedef Genode::Rpc_in_buffer<24> String;
virtual void feedback_mymsg(String &msg) = 0; GENODE_RPC(Rpc_feedback_mymsg, void, feedback_mymsg, String &); GENODE_RPC(Rpc_say_hello, Rpc_add, Rpc_feedback_mymsg);
------client/main.cc----------------- Hello::String string_mymsg = "hello from client"; h.feedback_mymsg(string_mymsg); PDBG("from server[%p] base:[%p] msg:%s size:%d\n", &string_mymsg, string_mymsg.base(), string_mymsg.string(), string_mymsg.size());
-------server/main.cc------------ void feedback_mymsg(String &msg) { msg = "hello from server"; PDBG("SERVER: base:[%p]", msg.base()); }
The client correctly prints out the size of the result message, but the base values is same as the server's.
------- Original Message ------- Sender : Christian Helmuth<christian.helmuth@...1...> Date : 2012-07-13 16:29 (GMT+09:00) Title : Re: Genode RPC: Handling vector parameters
Hello 정복득,
On Thu, Jul 12, 2012 at 09:16:19AM +0000, 정복득 wrote:
I need to use parameters of std::vectorstd::string type for my RPC program, but it doesn't seem to work. (I want to define a RPC function passing varible number of strings as a parameter. The number of strings is very flexible.) I read about the transferable argument types from the 11.05 release notes.
The RPC mechanism does not support (de)marshalling of complex types like std::vectorstd::string as the serialization of such types cannot be implemented in a generic way but needs type-specific serialization functions.
If vector isn't one of the transferable argument type, could you give me an alternative programming tip?
This issue comes up from time to time and we always encourage the users to enter a discussion about what they really want to achieve resp. to clarify the details of the use case. So, please allow me to give some background information:
* The RPC mechanism is just one basic synchronous communication mechanism. Therefore, it's suited for configuration interfaces and interfaces with simple parameters, i.e. C++ base or POD types. The mechanism is not inteded to support structured bulk traffic with complex serialization tasks.
* The base mechanism used for RPC is the IPC mechanism of the base platform, which is usually limited with regard to the maximum message size. For Fiasco.OC, the limiting factor is the size of the UTCB.
* Besides RPC, Genode also supports the packet-stream interface, which is a packet-based shared-memory mechanism (see os/include/os/packet_stream.h and os/include/packet_stream_rx/tx). The packet stream is well suited for bulk traffic and also supports asynchronous operation.
With this background, we could revisit your usage scenario and come up with an approach that fits best.
Unfortunately, the serialization of std::vectorstd::string is in any case out of the scope of the base framework, but should not be that hard.
Regards
Hello,
welcome to the list. :-)
Okay. Now I changed my rpc params to transferable types. I am using Rpc_in_buffer<> instead of std::string. I want to receive a feedback message from a server through an Rpc_in_buffer<> argument, but the client doesn't receive the results from the server correctly while working correclty with an character array.
I should not use Rpc_in_buffer for a reply message from a server?
That is right. 'Rpc_in_buffer' is specifically meant as an input parameter, hence the name. Let me give you a bit of the rationale behind this class template: The most basic way of passing strings as RPC function arguments is by using a compound object that contains a character array. For example:
struct File_name { char buffer[64]; };
This compound struct works for both directions as RPC argument or as RPC return value. However, this approach has two slight problems. First, it is a bit clumsy to use. It would be much nicer to pass a string directly to the RPC function at the client side. And second, the whole buffer is transferred regardless of the actual string length. Because 'buffer[64]' is just a bunch of bytes, this is the only sensible thing to do. Because most kernels support variable-sized messages, it would be nice to transfer only the elements of the buffer that carry any meaningful information to speed things up a bit. This is where 'Rpc_in_buffer' comes into play. It is a class template for the basic idea outlined above. Thanks to its implicit constructor that takes a null-terminated string as argument, it is quite convenient to use. And because 'Rpc_in_buffer' is specially handled in 'ipc_generic.h', only the actual payload is stuffed into the RPC message.
In the other direction (which you asked about) there is no such convenience function yet. This is simply because, until now, there was no need for it. In the framework, there is currently no single place (at least that I am aware of) where a string is returned. If we observe that this use case becomes frequent, we might add an 'Rpc_out_buffer' type. Until then, I suggest to use a compound type as mentioned above.
Regarding the general problem of communicating complex types from one process to another, Christian already mentioned the packet-stream facility. However, I would like to point out another approach that is somewhere in the middle: Using a dataspace shared between client and server as buffer for complex arguments combined with synchronous RPC for invoking the actual RPC function. You can find a brief explanation and pointers to code examples in the following posting:
http://sourceforge.net/mailarchive/forum.php?thread_name=op.v56pvpky50x9fi%4...
Best regards Norman