Como ya se vio en “Crear una applicación Unity 3 con Plugin de código nativo para iOS” podemos crear un plug in the código nativo para iOS en Unity 3. El problema es que por defecto no se pueden probar las llamadas a código nativo en el Simulador de Xcode. Probablemente no tenga mucho sentido probar una aplicación Unity 3 en el simulador ya que el rendimiento 3D puede variar mucho con el del dispositivo real, pero si todavía no tienes un dispositivo iOS puede servirte.
Dentro del proyecto Xcode en el fichero “Libraries/RegisterMonoModules.cpp
” se puede ver como las funciones definidas dentro del “extern” están dentro de un bloque que solo se procesa cuando el target NO ES el Simulator (#if !(TARGET_IPHONE_SIMULATOR)
). Tenemos que sacar de esos bloques tanto la definición de la función que registra las funciones (mono_dl_register_symbol
) como nuestras funciones propiamente dichas. Fijarse en las líneas marcadas en negrita a continuación:
#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); }
Podemos modificar el script “PostprocessBuildPlayer
” para no tener que hacer estos cambios a mano cada vez que generemos el proyecto Xcode. Un poco de awk
hace la magia (no es muy bonito el código pero funciona…):
#!/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
Probablemente sea una buena idea desactivar la opción “Dead Code Stripping” del proyecto Xcode (dentro de “Linking” en “Build Settings”) ya que Xcode puede pensar que las funciones definidas como externas no serán nunca llamadas desde Xcode ya que son llamadas desde Unity.
Fuente: http://answers.unity3d.com/questions/49945/gamekit-linker-failure.html?sort=oldest