Las siglas API las habrás visto más de una y de dos veces cuando lees artículos sobre software. Pero no todos saben qué es realmente una API. Por eso lo aclaramos en este artículo. Lo primero decir que son las siglas de Application Programming Interface, es decir, en español Interfaz de Programación de Aplicaciones. Y muchas veces genera confusiones incluso entre los que conocen algo de programación.
Por ejemplo, Arduino tiene su propia API de programación, ofreciendo una serie de funciones que puedes usar en Arduino IDE u otros entornos para programar el microcontrolador para que te permita crear tus proyectos. Pero… ¿sabrías decirme la diferencia entre una biblioteca de programación y una API? ¿existen diferencias entre un framework y una API?¿es lo mismo una API que una ABI? Existen muchas dudas que quizás siguen generando confusión y que ahora mismo vamos a dejar claro.
No sé si sabrás que los lenguajes de bajo nivel, como el ensamblador o ASM, dependen directamente de la arquitectura de hardware, mientras que los de alto nivel se abstraen del hardware para facilitar la tarea del programador, pero dependen del sistema operativo (syscalls) o de ciertas APIs, etc. Para que todo esto no te suene a chino, vamos a ver de qué se trata…
¿Qué es una API?
Una API es una herramienta con la que se dota a los desarrolladores para que tengan a su disposición una serie de funciones, subrutinas y procedimientos o métodos para la POO que se puede usar a través de las bibliotecas existentes. Entre lo que ofrece una API están desde funciones para crear apps simples, funciones relacionadas con la IA, con la generación de gráficos, gestión de recursos de hardware, etc.
Por ejemplo, seguro que te suenan APIs muy conocidas como la que ofrece Linux a través de la biblioteca glibc, o las gráficas como OpenGL y Vulkan, o también otras como OpenCL para computación heterogénea, OpenXR para realidad virtual y aumentada, etc. Otros sistemas operativos y software también incluyen sus propias APIs para que otros programadores puedan crear addons, plugins o módulos para dicho sistema, etc.
Ejemplo con Arduino
Si tienes una placa Arduino y usas frecuentemente Arduino IDE, o cualquier otro entorno de desarrollo para Arduino, conocerás que cuando creas un código haces uso de múltiples opciones para ordenar a tu microcontrolador que haga una serie de acciones. Por ejemplo, pinMode() es una función típica para configurar un pin de Arduino, ¿Verdad?
Cuando escribes pinMode(9, INPUT), por poner un ejemplo, estás indicando que el pin 9 de la placa Arduino debe trabajar como una entrada, es decir, el microcontrolador estará a la espera de la información que entre por ese pin para leerla y realizar una acción. Pero ¿alguna vez te has preguntado cómo es capaz de entender esa orden?
Pues bien, Arduino cuenta con una API de desarrollo que está puesta a nuestra disposición. A dicha API se le pueden agregar bibliotecas de terceros como hemos visto en multitud de ejemplos en este blog. Como las de SparkFun para ciertos sensores, etc. Con todo ello se pueden introducir las funciones en Arduino IDE y éste traducirá el código debidamente para cargarlo en la memoria del microcontrolador para que éste pueda procesarlo.
De no contar con dicha API no podrías crear estos programas para Arduino de modo tan simple, ya que deberíamos tratar de hacerlos en código ensamblador para el microcontrolador ATMega328P, es decir, en ASM para la arquitectura AVR. Y eso sería bastante más complicado, ya que tendrías que usar directamente las instrucciones disponibles por esta ISA. De ser así, no solo tendrías que conocer adecuadamente el repertorio de esa ISA, también otros aspectos como la cantidad de registros, etc. Es decir, deberías tener conocimientos a bajo nivel del hardware para el que estás trabajando.
Por ejemplo, el código ASM que deberías generar para que un LED titíle en un bucle sería:
<br data-mce-bogus="1"> .ORG 0x0000 ; the next instruction has to be written to ; address 0x0000 rjmp START ; the reset vector: jump to "main" START: ldi r16, low(RAMEND) ; set up the stack out SPL, r16 ldi r16, high(RAMEND) out SPH, r16 ldi r16, 0xFF ; load register 16 with 0xFF (all bits 1) out DDRB, r16 ; write the value in r16 (0xFF) to Data ; Direction Register B LOOP: sbi PortB, 5 ; switch off the LED rcall delay_05 cbi PortB, 5 ; wait for half a second ; switch it on rcall delay_05 ; wait for half a secon rjmp LOOP ; jump to loop DELAY_05: ; the subroutine: ldi r16, 31 ; load r16 with 31 OUTER_LOOP: ; outer loop label ldi r24, low(1021) ; load registers r24:r25 with 1021, our new ; init value ldi r25, high(1021) ; the loop label DELAY_LOOP: ; "add immediate to word": r24:r25 are ; incremented adiw r24, 1 ; if no overflow ("branch if not equal"), go ; back to "delay_loop" brne DELAY_LOOP dec r16 ; decrement r16 brne OUTER_LOOP ret ; and loop if outer loop not finished ; return from subroutine
Mientras que gracias a la API las facilidades son totales, escribiendo en alto nivel el siguiente código equivalente (mucho más corto e intuitivo):
<br data-mce-bogus="1"> int ledPin = 13; // LED que se encuentra en el pin 13 void setup(){ pinMode(ledPin, OUTPUT); // El p1n 13 será una salida digital } void loop(){ digitalWrite(ledPin, HIGH); // Enciende el LED delay(1000); // Pausa de 1 segundo digitalWrite(ledPin, LOW); // Apaga el LED delay(1000); // Pausa de 1 segundo
Diferencias con una ABI
ABI es un término menos conocido, es una Interfaz Binaria de Aplicación, o en inglés Application Binary Interface. En este caso es una interfaz entre módulos de un programa, generalmente entre una biblioteca o un sistema operativo a nivel lenguaje máquina para la arquitectura en la que te encuentras: SPARC, AMD64, ARM, PPC, RISC-V, etc.
Gracias a la ABI se determina la forma de llamar a las funciones, el formato binario que puede entender la máquina para la que estés compilando o las llamadas al sistema, como se gestionan las excepciones, cómo se pasan los datos, etc.
Diferencias con un Framework
Un framework o marco de trabajo es más un conjunto de herramientas a tu disposición para ayudar al desarrollo de un proyecto dado. El famework normalmente establece algunos estándares de codificación, proporciona componentes útiles, etc. Por ejemplo, JUnit es un marco para Java, o Symfony/Cake para PHP, etc.
Diferencias con un SDK y NDK
SDK es un Software Development Kit, es decir, un kit de desarrollo de software. Va más allá de lo que es un framework o una API. Un ejemplo podría ser Android Studio o iOS xCode, etc. Por ejemplo, en el primero de ellos, además de la propia Android API, se incluye también un IDE o entorno integrado de desarrollo para programar y compilar, bibliotecas, herramientas, etc.
Por otro lado, NDK (Native Development Kit) es un complemento. Por ejemplo, Android NDK permite a los desarrolladores reutilizar código en C/C++ introduciéndolo a las aplicaciones a través de JNI (Java Native Interface)…
Diferencias con una biblioteca
Por último, la biblioteca es una colección de código fuente reutilizable que facilita la vida a los programadores. Por ejemplo, dentro de la biblioteca stdio.h de C existe una función printf para imprimir un texto en pantalla. Para que eso sea posible se necesita un código fuente que haga que el sistema operativo haga esa tarea. Pero como es algo muy recurrente que se usa con frecuencia, simplemente con invocar a esa biblioteca se puede hacer uso de printf sin escribir todo el código desde cero. Es decir, dicho de otro modo, se pueden ver como bloques prefabricados.
Una biblioteca y una API pueden confundirse fácilmente, de hecho, las bibliotecas son envueltas dentro de una API. Ejemplo glibc…
Espero que tras esto tengas una idea más clara de qué es una API, ABI, un framework, un SDK y una biblioteca, además de poder diferenciar a partir de ahora entre ellos.