AutoRPC Overview

Call C and C++ functions directly
The AutoRPC plugin adds remote procedure call capability beyond what the default RPC functionality in RakPeer provides. In essence, it allows you to call procedures on remote systems using the same syntax as if they were local, and without the need to serialize or deserialize parameters. Internally, it uses assembly to push the parameter list on and off the stack. This does have limitiations however, as the system cannot determine the type of parameters past some basic template checks. Use the newer RPC3 system if you want more flexible functionality.

Requirements:

1. Function must be __cdecl
2. Parameters must be passable using memcpy (stack parameters only). Use SetOutgoingExtraData and GetIncomingExtraData to pass non-passable parameters "out of band".

Valid Callable Functions:

void _cdecl PrintNumber(int i, char c)
{
printf("%i %i", i, c);
}

struct Bytes {
char bytes[20];
}

void _cdecl PrintString(Bytes b)
{
printf("%s", b.bytes);
}

class MyClass
{
public:
int a;
MyClass() {a=10;}
virtual _cdecl PrintClass(void) { printf("%i", a); }
}

Setup

Create an instance of the plugin:
AutoRPC autoRpc;

Attach the plugin:
rakPeer->AttachPlugin(&autoRpc);

If calling C++ functions, create (or use an existing) instance of NetworkIDManager
NetworkIDManager networkIDManager;

If calling C++ functions, tell the plugin about your instance of NetworkIDManager
autoRpc.SetNetworkIDManager(&networkIDManager);

Registering a function

For C functions, just call RegisterFunction with the function pointer and a string identifier
autoRpc.RegisterFunction("cFunc0", cFunc0, false);

For C++ functions, use the macro to make things easier. It requires the complete function definition. See the definition of ARPC_REGISTER_CPP_FUNCTION in AutoRPC.h for a complete explanation of each parameter.
ARPC_REGISTER_CPP_FUNCTION(&autoRpc, "DerivedClass::objectMemberFunc", int, BaseClass, objectMemberFunc, (int a));

Calling a function
autoRpc.Call("myFunction", param1, param2, param3);

To designate the packet recipient, if this is a C call or C++ member function, etc. use the functions in the AutoRPC class. See AutoRPC.h for parameter documentation:
void SetTimestamp(RakNetTime timeStamp);
void SetSendParams(PacketPriority priority, PacketReliability reliability, char orderingChannel);
void SetRecipientAddress(SystemAddress systemAddress, bool broadcast);
void SetRecipientObject(NetworkID networkID);

On error, the remote system will send ID_RPC_REMOTE_ERROR. The error code is held in the 2nd byte, e.g. packet->data[1]. See the enumeration RPCErrorCodes for a full list of error codes.

Determining sender, etc.

There are two ways to get access to the sender, timestamp, and other parameters relevant to recieving a packet.

First, you can query the plugin if you know contextually that the called function is triggered from the network:
RakNetTime GetLastSenderTimestamp(void) const;
SystemAddress GetLastSenderAddress(void) const;
RakPeerInterface *GetRakPeer(void) const;
const char *GetCurrentExecution(void) const;

Second, you can add an AutoRPC pointer to the end of your function. This will be filled in automatically by the plugin when the function is called.

// Leave off last autoRPC param when calling the function
autoRpc.Call("myFunction", param1, param2, param3);

// When the function is called by the plugin, it is filled in automatically
void myFunction(int param1, int param2, int param3, AutoRPC *autoRPC)
{
if (autoRPC!=0){
// Called from the network
}
}

You can use this capability to relay the function call. If autoRPC is 0, then relay the call. Otherwise, this was a call from the network.

Pointers

Pointers are deferenced and the contents copied. Assuming the contents can be shallow copied as well, it is valid to pass

struct MyStruct
{
int a;
char b;
} myStruct;

autoRpc.Call("myFunction", &myStruct);

In this case the contents will not be endian swapped. If you need them to be endian swapped, pass each element individually.

See the sample project AutoRPC for an implementation of this system.

Constraints

memcpy only!

If you need to pass types with constructors, destructors, deep copy, use SetOutgoingExtraData() and GetIncomingExtraData().

Currently only tested on Windows, 32 bit compiler

On other compilers, be sure to test to make sure the sample works. The assembly code is in AutoRPC::CallWithStack in Source/AutoRPC.cpp. This notice will be updated as users report successful integration.

Possibly requires source linking, or building your own .lib and .dll

Because every system will generate the assembly differently, the included binaries may not work properly, especially with C++ object member functions. It is recommended you use the source, or rebuild the binaries on your own compiler before using.

See Also

Index Compiler Setup NetworkIDManager PluginInterface RemoteProcedureCalls RPC3