As far as I understand one has two options to port a C program to Native Client:
Implement a number of initializing functions like PPP_InitializeModule and PPP_GetInterface.
Simply pass your main function to PPAPI_SIMPLE_REGISTER_MAIN.
So the question is how can I implement JS message handling (handle messages emitted by JS code in native code) in the second case?
Take a look at some of the examples in the SDK in examples/demo directory: earth, voronoi, flock, pi_generator, and life all use ppapi_simple.
Here's basically how it works:
When using ppapi_simple, all events (e.g. input events, messages from JavaScript) are added to an event queue. The following code is from the life example (though some of it is modified and untested):
PSEventSetFilter(PSE_ALL);
while (true) {
PSEvent* ps_event;
/* Process all waiting events without blocking */
while ((ps_event = PSEventTryAcquire()) != NULL) {
earth.HandleEvent(ps_event);
PSEventRelease(ps_event);
}
...
}
HandleEvent then determines what kind of event it is, and handles it in an application specific way:
void ProcessEvent(PSEvent* ps_event) {
...
if (ps_event->type == PSE_INSTANCE_HANDLEINPUT) {
...
} else if (ps_event->type == PSE_INSTANCE_HANDLEMESSAGE) {
// ps_event->as_var is a PP_Var with the value sent from JavaScript.
// See docs for it here: https://developers.google.com/native-client/dev/pepperc/struct_p_p___var
if (ps_event->as_var->type == PP_VARTYPE_STRING) {
const char* message;
uint32_t len;
message = PSInterfaceVar()->VarToUtf8(ps_event->as_var, &len);
// Do something with the message. Note that it is NOT null-terminated.
}
}
To send messages back to JavaScript, use the PostMessage function on the messaging interface:
PP_Var message;
message = PSInterfaceVar()->VarFromUtf8("Hello, World!", 13);
// Send a string message to JavaScript
PSInterfaceMessaging()->PostMessage(PSGetInstanceId(), message);
// Release the string resource
PSInterfaceVar()->Release(message);
You can send and receive other JavaScript types too: ints, floats, arrays, array buffers, and dictionaries. See also PPB_VarArray, PPB_VarArrayBuffer and PPB_VarDictionary interfaces.
Related
I currently use the below callback to check the PAYLOAD of incoming MQTT messages, but does anyone know how I could continue to do this but also find messages coming under a specific TOPIC?
void callback(char * topic, byte * payload, unsigned int length) {
char p[length + 1];
memcpy(p, payload, length);
p[length] = NULL;
if (!strcmp(p, "home")) {
Particle.publish(DEVICE_NAME, HOME_MSSG, 60, PRIVATE);
} else if (!strcmp(p, "chome")) {
Particle.publish(DEVICE_NAME, CHOME_MSSG, 60, PRIVATE);
}
}
The topic can be handled in pretty much the same way as the payload; e.g.
if (!strcmp(topic, "thisIsATopic")) {
// do something
}
Note that the payload is copied for two reasons:
The buffer is reused once the callback returns (so if you store that pointer and refer to it later it may not contain what you expect).
The message is binary so it is important to ensure a \0 is added to the end if using functions like strcmp (to avoid overruns).
It looks like the library you are using copies the topic so you should be fine using that as-is (unlike with some other libraries).
I'm learning gRPC using the official doc, but found the method signature of client-streaming and bidirectional-streaming very confusing (the two are the same).
From the doc here, the function takes StreamObserver<ResponseType> as the input parameter and returns a StreamObserver<ResponseType> instance, as the following:
public StreamObserver<RequestType> bidirectionalStreamingExample(
StreamObserver<ResponseType> responseObserver)
But in my mind, it should take the RequestType type as input and returns the ResponseType type:
public StreamObserver<ResponseType> bidirectionalStreamingExample(
StreamObserver<RequestType> responseObserver)
This confuses me very much and I'm actually a little surprised that the answer didn't prompt up when I search is in google, I thought many people would have the same question. Am I missing something obvious here? Why would gRPC defines the signature like this?
Your confusion probably stems from being used to REST or non-streaming frameworks, where request-response is often mapped to a function's parameter-return. The paradigm shift here is that you're no longer supplying request-response, but rather channels to drop requests and responses. If you've studied C or C++, it's very much like going from
int get_square_root(int input);
to
void get_square_root(int input, int& output);
See how output's now a parameter? But in case that makes no sense at all (my fault :-) here's a more organic path:
Server Streaming
Let's start with the server streaming stub, even if your eventual goal is client streaming.
public void serverStreamingExample(
RequestType request,
StreamObserver<ResponseType> responseObserver)
Q: Why is the "response" in the parameter list? A: It's not the response that's in the parameter list, but rather a channel to feed the eventual response to. So for example:
public void serverStreamingExample(
RequestType request,
StreamObserver<ResponseType> responseObserver) {
ResponseType response = processRequest(request);
responseObserver.onNext(response); // this is the "return"
responseObserver.onCompleted();
}
Why? Because, the point of streaming is to keep alive a channel on which responses can keep flowing through. If you could only return 1 response and that's that, the function's done, then that's not a stream. By supplying a channel, you as the developer can choose to pass it along as needed, feeding it as many responses as you'd like via onNext() until you're satisfied and call onCompleted().
Client Streaming
Now, let's move on to the client streaming stub:
public StreamObserver<RequestType> clientStreamingExample(
StreamObserver<ResponseType> responseObserver)
Q: Wait, what! We know why the response is in the parameter list now, but how does it make sense to return a request? A: Again, we're not actually returning a request, but a channel for the client to drop requests! Why? Because the point of client streaming is to allow the client to supply requests in pieces. It can't do that with a single, traditional call to the server. So here's one way this can be implemented:
class ClientStreamingExample {
int piecesRcvd = 0;
public StreamObserver<RequestType> myClientStreamingEndpoint(
StreamObserver<ResponseType> responseObserver) {
return new StreamObserver<RequestType>() {
#Override
public void onNext(RequestType requestPiece) {
// do whatever you want with the request pieces
piecesRcvd++;
}
#Override
public void onCompleted() {
// when the client says they're done sending request pieces,
// send them a response back (but you don't have to! or it can
// be conditional!)
ResponseType response =
new ResponseType("received " + piecesRcvd + " pieces");
responseObserver.onNext(response);
responseObserver.onCompleted();
piecesRcvd = 0;
}
#Override
public void onError() {
piecesRcvd = 0;
}
};
}
}
You might have to spend a little time studying this to fully understand, but basically, since the client may now send a stream of requests, you have to define handlers for each request piece, as well as handlers for the client saying it's done or errored out. (In my example, I have the server only respond when the client says it's done, but you're free to do anything you want. You can even have the server respond even before the client says it's done or not respond at all.)
Bidirectional Streaming
This isn't really a thing! :-) What I mean is, tutorials just mean to point out that nothing's stopping you from implementing exactly the above, just on both sides. So you end up with 2 applications that send and receive requests in pieces, and send and receive responses. They call this setup bidirectional streaming, and they're correct to, but it's just a little misleading since it's not doing anything technically different from client streaming. That's exactly why the signatures are the same. IMHO, tutorials should just mention a note like I have here, rather than repeat the stub.
Optional: Just for "fun"...
We began with the C++ analogy of going from
int get_square_root(int input); // "traditional" request-response
to
void get_square_root(int input, int& output); // server streaming
Do we want to carry on this analogy? Of course we do.
🎵 Hello, C++ function pointers, my old friend... 🎶
void (*fnPtr)(int) get_square_root_fn(int& output); // client streaming
And a demonstration of its use(lessness):
int main() { // aka the client
int result;
void (*fnPtr)(int) = server.get_square_root_fn(result);
fnPtr(2);
std::cout << result << std::endl; // 1.4142 assuming the fn actually does sqrt
}
I have written a server using QTcpSocket. The server handles the POST request from client app. I use the content-length field to determine the end of the request body. The code is as follows:
int length = 0;
QString line = "";
while(this->canReadLine())
{
line = this.readLine();
if(line.contains("Content-Length"))
{
length = line.split(':')[1].toInt();
}
if(line == "\r\n")
{
break;
}
}
for(; this.bytesAvailable() < length; ){}
QString requestBody = this.readAll();
It works in my localhost. But when it is run on remote server, bytesAvailable always returns a fixed value: 0 or 2896. Is there something wrong in my code or the network is causing that?
The bytesAvailable() function only tells you how many bytes are in the internal buffer of QTcpSocket, it does not instruct it to look for more data coming across the network. Calling this function repeatedly is thus a pointless exercise and can cause your program to hang.
What you are trying to do is wait for more data to arrive. To do this, you must let your program go back to the event loop or call one of the blocking functions, like waitForReadyRead()
EDIT:
If you're using standard HTTP processing, also consider using QNetworkAccessManager along with QNetworkReply to simplify the data retrieval process.
I'm using PNaCl and I'm in a situation where first I receive a message that is handled in the 'HandleMessage' function as the normal way, but then in the current HandleMessage execution, I need to wait for a user input that would come from an other message in order to complete the execution.
I'm wondering if this is possible to do that (handling a message while already waiting in the 'HandleMessage' function) ? And if so, can someone give me a trick ?
Thanks !
HandleMessage is currently called on one thread, the main thread. So you cannot receive a message while you are handling another message.
We typically suggest you spawn a new thread to do your work, and leave the main thread to handle messages, and queue them for the new thread to handle. Take a look at the nacl_io_demo example in the SDK for an example of this technique (found in examples/demo/nacl_io).
Another solution is to use a state machine; i.e. keep track of your current state in a variable instead of on the stack.
For example:
enum State {
STATE_INIT,
STATE_WAITING_FOR_INPUT,
STATE_DO_OTHER_STUFF,
};
State state_;
virtual void HandleMessage(const pp::Var& var_message) {
switch (state_) {
case STATE_INIT:
if (var_message.AsString() == "first_message") {
state_ = STATE_WAITING_FOR_INPUT;
// Do some work before you need the user input ...
}
break;
case STATE_WAITING_FOR_INPUT:
if (var_message.AsString() == "user_input") {
// Do more work, now that we've received input from the user...
state_ = STATE_DO_OTHER_STUFF;
}
break;
}
}
VaComm component encapsulates communication with external devices through COM port. My program is communicating with measuring device using following code:
void Form::OnButton_Click()
{
VaComm1->PortNum = param.serialComm.port;
VaComm1->Open();
VaComm1->WriteText("bla bla\r\n");
Sleep(3000);
VaComm1->WriteText("another bla bla");
}
I have set OnRxChar event handler (through form designer) which looks like this:
void __fastcall TForm_Main::VaComm1RxChar(TObject *Sender, int Count)
{
AnsiString str = VaComm1->ReadText();
if (!str.IsEmpty())
{
// process received data
}
}
Problem is that this event is not fired even when data were received (can be checked through calling TVaComm::ReadText method in infinite loop). Also sending of two commands to connected device was successfull (can be seen on device display). What else is needed beside opening COM port to receive OnRxChar events when there are some data in input buffer? I also don't understand what is the purpose of sibling component TVaBuffer? Currently i am not using it and can receive data through method ReadText (as i have written above).
Most CommPort components I have seen depend on the calling thread having an active message loop in order to fire asynchronous events. In this case, your main thread is blocked from processing new messages until OnButon_Click() exits. Try something more like this instead:
void Form::OnButton_Click()
{
VaComm1->PortNum = param.serialComm.port;
VaComm1->Open();
VaComm1->WriteText("bla bla\r\n");
}
void __fastcall TForm_Main::VaComm1RxChar(TObject *Sender, int Count)
{
AnsiString str = VaComm1->ReadText();
if (!str.IsEmpty())
{
// process received data
if (str is a reply you are expecting)
VaComm1->WriteText("another bla bla");
}
}