Hacer referencia a bibliotecas nativas en Xamarin.iOS
Xamarin.iOS admite la vinculación con bibliotecas y bibliotecas Objective-C nativas de C. En este documento se describe cómo vincular las bibliotecas nativas de C con el proyecto de Xamarin.iOS. Para obtener información sobre cómo hacer lo mismo para Objective-C las bibliotecas, consulte nuestro Binding Objective-C Types documento.
Compilar bibliotecas nativas universales (i386, ARMv7 y ARM64)
A menudo es conveniente compilar las bibliotecas nativas para cada una de las plataformas admitidas para el desarrollo de iOS (i386 para el simulador y ARMv7/ARM64 para los propios dispositivos). Si ya tiene un proyecto de Xcode para la biblioteca, esto es realmente trivial.
Para compilar la versión i386 de la biblioteca nativa, ejecute el siguiente comando desde un terminal:
/Developer/usr/bin/xcodebuild -project MyProject.xcodeproj -target MyLibrary -sdk iphonesimulator -arch i386 -configuration Release clean build
Esto dará como resultado una biblioteca estática nativa en MyProject.xcodeproj/build/Release-iphonesimulator/ . Copie (o mueva) el archivo de archivo de biblioteca (libMyLibrary.a) a un lugar seguro para su uso posterior, asíbiéndole un nombre único (como libMyLibrary-i386.a)para que no entre en conflicto con las versiones arm64 y armv7 de la misma biblioteca que va a compilar a continuación.
Para compilar la versión ARM64 de la biblioteca nativa, ejecute el siguiente comando:
/Developer/usr/bin/xcodebuild -project MyProject.xcodeproj -target MyLibrary -sdk iphoneos -arch arm64 -configuration Release clean build
Esta vez, la biblioteca nativa creada se ubicará en MyProject.xcodeproj/build/Release-iphoneos/ . Una vez más, copie (o mueva) este archivo a una ubicación segura y vuelva a asignarle un nombre como libMyLibrary-arm64.a para que no entre en conflicto.
Ahora compile la versión ARMv7 de la biblioteca:
/Developer/usr/bin/xcodebuild -project MyProject.xcodeproj -target MyLibrary -sdk iphoneos -arch armv7 -configuration Release clean build
Copie (o mueva) el archivo de biblioteca resultante a la misma ubicación en la que movió las otras 2 versiones de la biblioteca y asímícelo a algo parecido a libMyLibrary-armv7.a.
Para crear un binario universal, puede usar la lipo herramienta de la siguiente manera:
lipo -create -output libMyLibrary.a libMyLibrary-i386.a libMyLibrary-arm64.a libMyLibrary-armv7.a
Esto crea una biblioteca universal (fat) que será adecuada para usarse para todos los destinos libMyLibrary.a de desarrollo de iOS.
Falta la arquitectura necesaria i386
Si está recibiendo un mensaje o en la salida en tiempo de ejecución al intentar consumir una biblioteca en el simulador de iOS, es probable que la biblioteca no se haya compilado para la arquitectura does not implement methodSignatureForSelectordoes not implement doesNotRecognizeSelector i386 (consulte la sección Compilación de Objective-Cdoes not implement methodSignatureForSelector universales anterior).
Para comprobar las arquitecturas admitidas por una biblioteca determinada, use el siguiente comando en terminal:
lipo -info /full/path/to/libraryname.a
Donde /full/path/to/ es la ruta de acceso completa a la biblioteca que se está consumiendo libraryname.a y es el nombre de la biblioteca en cuestión.
Si tiene el origen de la biblioteca, deberá compilarlo y agruparlo también para la arquitectura i386, si desea probar la aplicación en el simulador de iOS.
Vinculación de la biblioteca
Cualquier biblioteca de terceros que consuma debe vincularse estáticamente a la aplicación.
Si quisiera vincular estáticamente la biblioteca "libMyLibrary.a" que obtuvo de Internet o compilar con Xcode, tendría que hacer algunas cosas:
- Bring the Library into your project (Traer la biblioteca al proyecto)
- Configuración de Xamarin.iOS para vincular la biblioteca
- Acceda a los métodos desde la biblioteca.
Para traer la biblioteca al proyecto, seleccione el proyecto en el explorador de soluciones y presione Comando+Opción+un. Vaya a libMyLibrary.a y agrégrélo al proyecto. Cuando se le solicite, Visual Studio para Mac o Visual Studio copiarlo en el proyecto. Después de agregarlo, busque libFoo.a en el proyecto, haga clic con el botón derecho en él y establezca acción de compilación enninguno.
Para configurar Xamarin.iOSpara vincular la biblioteca , en las opciones del proyecto para el archivo ejecutable final (no la biblioteca en sí, sino el programa final) debe agregar en el argumento Adicional de compilación de iOS(que forman parte de las opciones del proyecto) la opción "-gcc_flags" seguida de una cadena entrecomillada que contiene todas las bibliotecas adicionales necesarias para el programa. por ejemplo:
-gcc_flags "-L${ProjectDir} -lMylibrary -force_load ${ProjectDir}/libMyLibrary.a"
En el ejemplo anterior se vinculará libMyLibrary.a
Puede usar para especificar cualquier conjunto de argumentos de línea de comandos para pasar al compilador GCC que se usa para realizar el vínculo -gcc_flags final del ejecutable. Por ejemplo, esta línea de comandos también hace referencia al marco CFNetwork:
-gcc_flags "-L${ProjectDir} -lMylibrary -lSystemLibrary -framework CFNetwork -force_load ${ProjectDir}/libMyLibrary.a"
Si la biblioteca nativa contiene código de C++, también debe pasar la marca -cxx en los "argumentos adicionales" para que Xamarin.iOS sepa usar el compilador correcto. Para C++ las opciones anteriores tendrían el siguiente aspecto:
-cxx -gcc_flags "-L${ProjectDir} -lMylibrary -lSystemLibrary -framework CFNetwork -force_load ${ProjectDir}/libMyLibrary.a"
Acceso a métodos de C desde C #
Hay dos tipos de bibliotecas nativas disponibles en iOS:
Bibliotecas compartidas que forman parte del sistema operativo.
Bibliotecas estáticas que se envían con la aplicación.
Para acceder a los métodos definidos en cualquiera de ellos, se usa la funcionalidad P/Invoke de Mono, que es la misma tecnología que usaría en .NET, que es aproximadamente:
- Determinar qué función de C desea invocar
- Determinación de su firma
- Determinación de la biblioteca en la que reside
- Escribir la declaración P/Invoke adecuada
Al usar P/Invoke, debe especificar la ruta de acceso de la biblioteca con la que está vinculando. Al usar bibliotecas compartidas de iOS, puede codificar de forma permanente la ruta de acceso o puede usar las constantes de conveniencia que hemos definido en , estas constantes deben cubrir las Constants bibliotecas compartidas de iOS.
Por ejemplo, si desea invocar el método UIRectFrameUsingBlendMode de la biblioteca UIKit de Apple que tiene esta firma en C:
void UIRectFrameUsingBlendMode (CGRect rect, CGBlendMode mode);
La declaración P/Invoke tendría el siguiente aspecto:
[DllImport (Constants.UIKitLibrary,EntryPoint="UIRectFrameUsingBlendMode")]
public extern static void RectFrameUsingBlendMode (RectangleF rect, CGBlendMode blendMode);
Constants.UIKitLibrary es simplemente una constante definida como "/System/Library/Frameworks/UIKit.framework/UIKit", entryPoint nos permite especificar opcionalmente el nombre externo (UIRectFramUsingBlendMode) al exponer un nombre diferente en C#, el rectFrameUsingBlendMode más corto.
Acceso a C Dylibs
Si tiene la necesidad de consumir un C Dylib en la aplicación Xamarin.iOS, es necesario realizar una configuración adicional antes de llamar al DllImport atributo .
Por ejemplo, si tenemos un con un método al que llamaremos en nuestra aplicación, es necesario informar a Xamarin.iOS de la ubicación de la biblioteca antes de intentar Animal.dylibAnimal_Version consumirla.
Para ello, edite el Main.CS archivo y haga que sea parecido al siguiente:
static void Main (string[] args)
{
// Load Dylib
MonoTouch.ObjCRuntime.Dlfcn.dlopen ("/full/path/to/Animal.dylib", 0);
// Start application
UIApplication.Main (args, null, "AppDelegate");
}
Donde /full/path/to/ es la ruta de acceso completa al dylib que se está consumiendo. Con este código en su lugar, podemos vincular al Animal_Version método como se muestra a continuación:
[DllImport("Animal.dylib", EntryPoint="Animal_Version")]
public static extern double AnimalLibraryVersion();
Bibliotecas estáticas
Puesto que solo puede usar bibliotecas estáticas en iOS, no hay ninguna biblioteca compartida externa con la que vincular, por lo que el parámetro path del atributo DllImport debe usar el nombre especial (tenga en cuenta los caracteres de subrayado doble al principio del nombre) en lugar del nombre de la ruta __Internal de acceso.
Esto obliga a DllImport a buscar el símbolo del método al que se hace referencia en el programa actual, en lugar de intentar cargarlo desde una biblioteca compartida.