Wednesday, September 12, 2012

C to Unity Callback

This is an old post migrated from my previous blog (09/01/2012). I apologize if any info seems outdated.

This post will be sort of specific to those of you who may be writing/integrating an unmanaged API into Unity.
You might find yourself in a situation where some event or request may take place in your API and you need to notify Unity of this. One option is polling and that might be fine…but sometimes that can be sloppy, somewhat inefficient, or maybe just a poor way of solving your problem. Another option using callback.
In my simple example, the API is going to receive a network message then via function pointers we will call a function in Unity passing in the message . I’m actually going to be yanking some of this code directly out of my GummyNet API.
The first thing you want to do is define the type of function used for the callback. Notice that I’m passing the info, a string, as a parameter.
typedef void (__stdcall *OnGummyMessage_Callback)(char*);
You then need to set up a handler. We will be assigning our Unity function to this.
static OnGummyMessage_Callback OnGummyMessage;
You will also need a C function that Unity calls to assign the function pointer. It might look something like this:
EXPORT_API void SetCallback_OnGummyMessage(OnGummyMessage_Callback funcPtr)
{
 OnGummyMessage = funcPtr;
}
Now the Unity Side. Our objective here is to write the import for our set function. Declare delegate object (basically a  function pointer) that defines our method type instantiate it, and pass it to via our set function.
//Declaring the delegate
public delegate void OnGummyMessage_Callback(string msg);
 
//Instantiate the delegate and pass it
void RegisterCallbacks()
{
 OnGummyMessage_Callback onMsgCB = new OnGummyMessage_Callback(this.OnGummyMessage);
 SetCallback_OnGummyMessage(onMsgCB);
}
 
public void OnGummyMessage(string msg)
{
 print("receveied msg: " +msg);
}
 
//Importing the set function
[DllImport ("gummy_server")]
private static extern void SetCallback_OnGummyMessage(OnGummyMessage_Callback funcPtr);
Now when we Invoke our handler (shown below) in the API the C# OnGummyMessage should get called :)
...
//pass the message
OnGummyMessage((char*)data );
...