1 / 3

Writing native iOS and Android Unity Plugins

Unity usually restricts the use .Net sockets on Android & iOS, this blog talks about how native socket APIs (BSD C socket) have to be used for seamless real-time communication. Using the example of a library for creating a native socket and returning its socket descriptor, this is a comprehensive guide to easily create native iOS & Android Unity plugins.

shephertz
Download Presentation

Writing native iOS and Android Unity Plugins

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Writing native iOS and Android Unity Plugins We just released our latest AppWarp Unity SDK update which includes support for building for iOS and Android from Unity Free. Since Unity restricts the use of .Net sockets on these platforms, native socket APIs (BSD C socket) have to be used if you want to do socket communication. In this post I will share my experience and on how we went about doing this. There are two requirements when communicating with native unmanaged C code from managed .Net C# code. First you need to be able to call functions with arguments from C# to C and the second is to return data from native code back to C#. The below diagram illustrates how the code is structured. We will use the example of a library for creating a native socket and returning its socket descriptor. Then we will see how we can read data from the native socket by passing the socket descriptor and a managed buffer which will be filled in by the native library code. Quick Tip: Get all the ready made widgets for free here. Building the plugins: Lets first understand how we build the native plugins. For iOS, this is quite straight forward as you simply have to create a new “iOS Framework and Library” project from XCode. Then add a C file to it and write your native code in it. For example in our case we create a file Socket.c and add the following function in it (skipped the header include statements for brevity). int _Create() {

  2. int sockd = socket(AF_INET, SOCK_STREAM, 0); return sockd; } Compile and build from XCode and it will generate the library file (eg: libiOSNativeSocket.a in my case). In case of Android, you’ll need to useAndroid NDK to build the library. Download and add ndk-build to your path. While its useful to have a basic understanding of how NDK works but not absolutely required for the purpose of this post. Add your C file in a folder and name it “jni”. In this folder, you also need to add a file named Android.mk. It should look like below. LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_LDLIBS := -llog LOCAL_MODULE := socket_android LOCAL_SRC_FILES := Socket.c include $(BUILD_SHARED_LIBRARY) Now navigate to the parent directory of the jni folder and execute ndk-build command. If successful, it will create a libs folder and put the generated library in it (eg: libsocket_android.so in my case). Calling the plugin code from Unity Now that we’ve built the plugins, we are ready to call them from Unity code. You first need to declare the native functions that you will use in managed code. In our example [DllImport ("__Internal")] privatestatic extern int _Create (); Note that the “__Internal” name is used for iOS plugins. For android plugins you need to use the name of the native library that you have built for example if your android library’s name is “libsocket_android.so”, you will declare a function in it as follows [DllImport ("socket_android")] privatestatic extern int _Create (); Note that name should not include the prefix (‘lib’) nor the extension (‘.so’) of the filename. Once declared you can use the functions in your application. Note that its a good practice to check the platform when invoking these methods in Unity. For example if (Application.platform == RuntimePlatform.IPhonePlayer){ int _socketFd = _Create ();

  3. } Passing data buffers between Unity and native code Now we’ve covered the basic setup of communication across managed C# Unity and unmnagaed C library, we can look at a slightly more trick use case. The scenario is that we want to create buffer (byte array) in C# and pass it to the native library. The native library will fill it with what it reads from the socket and return the number of bytes read. The following is the simple native C code. int _Read(int sockd, char* buff, int buffLen) { ssize_t numRead = recv(sockd, buff, buffLen, 0); return numRead; } The corresponding managed C# code which uses this is non-trivial. The declaration of this in C# code is done as follows. Note the use of IntPtr for byte array starting address. [DllImport ("__Internal")] privatestatic extern int _Read (int sockfd, IntPtr msg, int size); To using this native method in C# code, we first create a byte array. Then we need to get the native handle of this memory and tell the Mono GC to pin it. This is so that the GC doesn’t free this memory while its being used by the native library. Once the function returns, we call free to inform the GC that the native handle is not being used anymore. byte[] buffer = newbyte[MAX_BUFFER_SIZE]; GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned); if (Application.platform == RuntimePlatform.IPhonePlayer) { retVal = _Read(_SocketFd, handle.AddrOfPinnedObject(), buffer.Length); handle.Free(); } Get started with Unity3D for AppWarp here. I hope this post was useful to readers who are planning to write native mobile plugins for Unity. Send us a mail on support@shephertz.com with your questions and comments.

More Related