Using the Xcode Simulator with a Unity 3 Native iOS Plug-In

As you saw in “Building a Unity 3 Application with Native Plugin for iOS” we can create a plug in for native code in iOS with Unity 3. The problem is that by default you can’t test it on the Simulator of Xcode. May be it doesn’t make too much sense to use the Simulator to try a Unity 3 application as the performance in 3D applications may vary significantly from the real device, but if you still don’t own a iOS device you can save the day with this.

Inside the Xcode project in the “Libraries/RegisterMonoModules.cpp” file you can see how the calls to the functions registered as “extern” are inside a block that is only processed it the target IS NOT the Simulator (#if !(TARGET_IPHONE_SIMULATOR)). So we have to pull out from that block both the definition of the function that registers our functions (mono_dl_register_symbol) and our functions them self. Look at the bold lines in the following code:

#include "RegisterMonoModules.h"

extern bool gEnableGyroscope;

extern "C"
{
        typedef void* gpointer;
        typedef int gboolean;
#if !(TARGET_IPHONE_SIMULATOR)
        const char*                     UnityIPhoneRuntimeVersion = "3.5.0f5";

        extern int                      mono_ficall_flag;
        void                            mono_aot_register_module(gpointer *aot_info);
        extern gboolean         mono_aot_only;
        extern gpointer*        mono_aot_module_Assembly_CSharp_firstpass_info; // Assembly-CSharp-firstpass.dll
        extern gpointer*        mono_aot_module_UnityEngine_info; // UnityEngine.dll
        extern gpointer*        mono_aot_module_mscorlib_info; // mscorlib.dll
#endif // !(TARGET_IPHONE_SIMULATOR)
        void                         mono_dl_register_symbol (const char* name, void *addr);
        void    _PassStructFromObjCToUnity();
        void    _Test();
}
void RegisterMonoModules()
{
    gEnableGyroscope = false;
#if !(TARGET_IPHONE_SIMULATOR)
        mono_aot_only = true;
        mono_ficall_flag = false;
        mono_aot_register_module(mono_aot_module_Assembly_CSharp_firstpass_info);
        mono_aot_register_module(mono_aot_module_UnityEngine_info);
        mono_aot_register_module(mono_aot_module_mscorlib_info);


#endif // !(TARGET_IPHONE_SIMULATOR)
        mono_dl_register_symbol("_PassStructFromObjCToUnity", (void*)&_PassStructFromObjCToUnity);
        mono_dl_register_symbol("_HaveObjCDoSomething", (void*)&_HaveObjCDoSomething);
}

We can modify the “PostprocessBuildPlayerscript so we don’t have to do this by hand every time we change our code. Some awk magic will do the trick (not very fancy but it works…):

#!/bin/bash
cp -fR ./iOS\ Build/Libraries ~/Documents/Xcode/my-project/
cp -fR ./iOS\ Build/Data ~/Documents/Xcode/my-project/
rm file.tmp
awk '
{
  if ($0 == "#if !(TARGET_IPHONE_SIMULATOR)" && NR == 9) {
    getline var1;
    getline var2;
    printf "%s\n%s\n%s\n", var2, $0, var1 >> "file.tmp"
  } else if (NR == 32) {
     printf "#endif // !(TARGET_IPHONE_SIMULATOR)" >> "file.tmp"
     printf "\n%s\n", $0 >> "file.tmp"
  } else if ($0 == "#endif // !(TARGET_IPHONE_SIMULATOR)" && NR > 32) {
  } else {
    print $0 >> "file.tmp"
  }
}' ~/Documents/Xcode/my-project/Libraries/RegisterMonoModules.cpp
mv file.tmp ~/Documents/Xcode/my-project/Libraries/RegisterMonoModules.cpp

It is probably a good idea to deactivate “Dead Code Stripping” option in the Xcode project (located in “Linking” from the “Build Settings”) as Xcode might think our extern defined functions will never be called as they are called only from Unity and not from Xcode.

Source: http://answers.unity3d.com/questions/49945/gamekit-linker-failure.html?sort=oldest

Leave a comment ?

2 Comments.

  1. Thank you very much!!! You realy help me!

Reply to Aleksey ¬
Cancel reply

Trackbacks and Pingbacks: