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 “PostprocessBuildPlayer
” script 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