Confirmed users
699
edits
Line 53: | Line 53: | ||
== Implement your protocol's generated C++ interface == | == Implement your protocol's generated C++ interface == | ||
Like Mozilla's IDL compiler, the IPDL compiler generates skeleton, concrete C++ implementations for the "abstract" classes it spits out. We'll add our "Hello, world!" printing code to those skeleton implementations in this step. | |||
Open <code>$OBJDIR/ipc/ipdl/_ipdlheaders/mozilla/test/TestProtocolChild.h</code> and <code>$OBJDIR/ipc/ipdl/_ipdlheaders/mozilla/test/TestProtocolParent.h</code>. Look for the sections marked <code>// Skeleton implementation of abstract actor class</code>; you should see something like the following. | |||
// ----- [in TestProtocolChild.h] ----- | |||
// Header file contents | |||
class ActorImpl : | |||
public TestProtocolChild | |||
{ | |||
virtual nsresult RecvHello(); | |||
ActorImpl(); | |||
virtual ~ActorImpl(); | |||
}; | |||
// C++ file contents | |||
nsresult ActorImpl::RecvHello() | |||
{ | |||
return NS_ERROR_NOT_IMPLEMENTED; | |||
} | |||
ActorImpl::ActorImpl() | |||
{ | |||
} | |||
ActorImpl::~ActorImpl() | |||
{ | |||
} | |||
// ----- [in TestProtocolParent.h] ----- | |||
// Header file contents | |||
class ActorImpl : | |||
public TestProtocolParent | |||
{ | |||
virtual nsresult RecvWorld(); | |||
ActorImpl(); | |||
virtual ~ActorImpl(); | |||
}; | |||
// C++ file contents | |||
nsresult ActorImpl::RecvWorld() | |||
{ | |||
return NS_ERROR_NOT_IMPLEMENTED; | |||
} | |||
ActorImpl::ActorImpl() | |||
{ | |||
} | |||
ActorImpl::~ActorImpl() | |||
{ | |||
} | |||
Looking past the odd fact that both skeletons are named "ActorImpl," note the substantial difference between the two skeletons: the ProtocolChild requires your C++ code to implement the code that acts on receiving a "Hello()" message, whereas the ProtocolParent requires your C++ code to implement the "World()" handler. IPDL generates boilerplate code to ''send'' these messages, but it has no idea what you want to do upon ''receiving'' them. | |||
'''NOTE''': if you don't implement these functions, libxul will not link. | |||
Now we'll make these skeletons do something useful. Take the code marked "// Header contents" in the ProtocolChild.h header and put it in a file called <code>ipc/test-harness/TestChild.h</code>. Rename "ActorImpl" to "TestChild," and make the constructor and destructor public. Put it inside the mozilla::test namespace. Next, take the code marked "// C++ file contents", put it in a file called <code>ipc/test-harness/TestChild.cpp</code>, and s/ActorImpl/TestChild/g again. Finally, repeat for the ProtocolParent.h header, creating TestParent.h and .cpp files. | |||
As mentioned above, the existing test-harness calls into <code>TestParent::DoStuff</code> when it has finished low-level initialization. Let's implement that method now. | |||
void TestParent::DoStuff() | |||
{ | |||
puts("[TestParent] in DoStuff()"); | |||
SendHello(); | |||
} | |||
This code will print the string above to stdout, then send the "Hello()" message to the TestChild actor. When the TestChild actor receives that message, its <code>RecvHello()</code> method will be called. Let's next implement that. Change its skeleton definition to | |||
nsresult TestChild::RecvHello() | |||
{ | |||
puts("[TestChild] Hello, "); | |||
SendWorld(); | |||
return NS_OK; | |||
} | |||
As you might guess, this will print "Hello, " to stdout and then send the "World()" message back to the TestParent. And, you got it, this will in turn cause the parent actor's <code>RecvWorld()</code> handler to be invoked. Let's finally implement that. | |||
nsresult TestParent::RecvWorld() | |||
{ | |||
puts("[TestParent] world!"); | |||
return NS_OK; | |||
} | |||
Now we're ready to compile and run the C++ code. | |||
== Put it all together == | == Put it all together == |