De Wikipedia, la enciclopedia libre
Saltar a navegación Saltar a búsqueda

Una interfaz de función externa ( FFI ) es un mecanismo mediante el cual un programa escrito en un lenguaje de programación puede llamar a rutinas o hacer uso de servicios escritos en otro.

Nombrar [ editar ]

El término proviene de la especificación de Common Lisp , que se refiere explícitamente a las características del lenguaje para llamadas entre lenguajes como tales; [1] el término también es utilizado oficialmente por los lenguajes de programación Haskell [2] y Python . [3] Otros lenguajes utilizan otra terminología: el lenguaje de programación Ada habla de " enlaces de lenguaje ", mientras que Java se refiere a su FFI como JNI ( Java Native Interface ) o JNA ( Java Native Access ). La interfaz de función externa se ha convertido en una terminología genérica para los mecanismos que proporcionan tales servicios.

Operación [ editar ]

La función principal de una interfaz de función extranjera es emparejar la semántica y las convenciones de llamada de un lenguaje de programación (el lenguaje anfitrión , o el lenguaje que define el FFI), con la semántica y las convenciones de otro (el lenguaje invitado ). Este proceso también debe tener en cuenta los entornos de ejecución y / o las interfaces binarias de la aplicación de ambos. Esto se puede hacer de varias maneras:

  • Exigir que las funciones del idioma invitado que deben ser invocables en el idioma anfitrión se especifiquen o implementen de una manera particular; a menudo usando una biblioteca de compatibilidad de algún tipo.
  • Uso de una herramienta para "envolver" automáticamente las funciones del idioma invitado con el código de cola apropiado , que realiza cualquier traducción necesaria.
  • Uso de bibliotecas contenedoras
  • Restringir el conjunto de capacidades del idioma anfitrión que se pueden utilizar en varios idiomas. Por ejemplo, las funciones de C ++ llamadas desde C pueden no incluir (en general) parámetros de referencia o lanzar excepciones.

Las FFI pueden verse complicadas por las siguientes consideraciones:

  • Si un idioma admite la recolección de basura (GC) y el otro no; Se debe tener cuidado de que el código de idioma que no sea de GC no haga nada que cause que el GC del otro código falle. En JNI, por ejemplo, el código C que "se aferra a" referencias de objetos que recibe de Java debe "registrar" este hecho con el entorno de ejecución de Java (JRE); de lo contrario, Java puede eliminar objetos antes de que C haya terminado con ellos. (El código C también debe liberar explícitamente su enlace a cualquier objeto de este tipo una vez que C ya no necesite ese objeto).
  • Los objetos o tipos de datos complicados o no triviales pueden ser difíciles de mapear de un entorno a otro.
  • Es posible que ambos idiomas no mantengan referencias a la misma instancia de un objeto mutable, debido al problema de mapeo anterior.
  • Es posible que uno o ambos idiomas se estén ejecutando en una máquina virtual (VM); además, si ambos lo son, probablemente serán máquinas virtuales diferentes.
  • La herencia entre lenguajes y otras diferencias, como entre sistemas de tipos o entre modelos de composición de objetos , pueden resultar especialmente difíciles.

Por idioma [ editar ]

Ejemplos de FFI incluyen:

  • Vinculaciones de lenguaje Ada , que permiten no solo llamar a funciones externas, sino también exportar sus funciones y métodos para ser llamados desde un código que no es Ada. [4]
  • C ++ tiene un FFI trivial con C , ya que los lenguajes comparten un subconjunto común significativo. El efecto principal de la declaración "C" externa en C ++ es deshabilitar la manipulación de nombres de C ++ .
  • Clean proporciona un FFI bidireccional con todos los idiomas siguiendo C o la convención de llamadas stdcall . [5] [6]
  • CNI , alternativa a JNI utilizada en el entorno del compilador GNU.
  • D lo hace de la misma manera que C ++ , con extern "C" a través de extern (C ++)
  • Dart incluye la biblioteca dart: ffi [7] para llamar al código C nativo para aplicaciones móviles, de línea de comandos y de servidor
  • Los lenguajes dinámicos , como Python , Perl , Tcl y Ruby , proporcionan un fácil acceso al código nativo escrito en C / C ++ (o cualquier otro lenguaje que obedezca las convenciones de llamadas de C / C ++).
  • Factor tiene FFI para C, Fortran , Objective-C y Windows COM ; todos estos permiten importar y llamar dinámicamente a bibliotecas compartidas arbitrarias.
  • Las FFI de Common Lisp y Haskell
  • Fortran 2003 tiene un módulo ISO_C_BINDING que proporciona tipos de datos interoperables (tanto tipos intrínsecos como estructuras POD), punteros interoperables, almacenes de datos globales interoperables y mecanismos para llamar a C desde Fortran y para llamar a Fortran desde C. [8]
  • Go puede llamar al código C directamente a través del "C"pseudopaquete. [9]
  • GWT , en el que Java se compila en JavaScript, tiene una FFI llamada JSNI que permite que la fuente Java llame a funciones JavaScript arbitrarias y que JavaScript vuelva a llamar a Java.
  • JNI , que proporciona una interfaz entre Java y C / C ++, los lenguajes de sistemas preferidos en la mayoría de los sistemas donde se implementa Java. JNA proporciona una interfaz con bibliotecas nativas sin tener que escribir código adhesivo . Otro ejemplo es JNR
  • Nim tiene una FFI que le permite utilizar fuentes de C , C ++ y Objective-C . También puede interactuar con Javascript.
  • Julia tiene una ccallpalabra clave para llamar a C (y otros lenguajes, por ejemplo, Fortran); [10] mientras que los paquetes, que proporcionan un soporte similar sin repetición, están disponibles para algunos lenguajes, por ejemplo, para Python [11] (para, por ejemplo, proporcionar soporte OO y soporte GC), Java (y admite otros lenguajes JDK, como Scala) y R El uso interactivo con C ++ también es posible con el paquete Cxx.jl.
  • PHP proporciona FFI a C. [12]
  • Ruby proporciona FFI a través de la gema ffi o mediante el violín de la biblioteca estándar .
requiere  'violín'libm  =  violín . dlopen ( '/lib/libm.so.6' )# Equivalente a: doble piso (doble x); piso  =  Fiddle :: Función . new (  libm . sym ( 'piso' ),  # ptr es una función referenciada (o símbolo), de Fiddle :: Handle.  [ Fiddle :: TYPE_DOUBLE ] ,  # args es una matriz de argumentos, pasados ​​a la función ptr .  Fiddle :: TYPE_DOUBLE  # ret_type es el tipo de retorno de la función )# Equivalente a: piso (3.14159); piso . llamar ( 3 . 14159 )  # => 3.0
  • Python proporciona los módulos ctypes y cffi . Por ejemplo, el módulo ctypes puede cargar funciones C desde bibliotecas / DLL compartidas sobre la marcha y traducir tipos de datos simples automáticamente entre la semántica de Python y C de la siguiente manera:
    importar  ctypes libc  =  ctypes . CDLL ( '/lib/libc.so.6' )  # Bajo Linux / Unix t  =  libc . time ( None )  # Código C equivalente: t = time (NULL) print ( t )
  • P / Invoke , que proporciona una interfaz entre Microsoft Common Language Runtime y el código nativo.
  • Racket tiene una FFI nativa basada en gran medida en macros que permite importar bibliotecas compartidas arbitrarias de forma dinámica. [13] [14]
  • Raku puede llamar a Ruby , Python , Perl , Brainfuck , Lua , C , C ++ , Go y Scheme Guile / Gambit [15] [16]
  • Rust también define una interfaz de función ajena. [17]
  • Visual Basic tiene una sintaxis declarativa que le permite llamar a funciones C no Unicode.
  • Una de las bases del modelo de objetos componentes es un formato de interfaz común, que utiliza de forma nativa los mismos tipos que Visual Basic para cadenas y matrices.
  • LuaJIT, una implementación justo a tiempo de Lua , tiene una FFI que permite "llamar a funciones C externas y usar estructuras de datos C a partir de código Lua puro". [18]
  • PhoneGap (fue llamado por el nombre Apache Callback, pero ahora Apache Cordova) es una plataforma para construir aplicaciones móviles nativas usando HTML, CSS y JavaScript. Además, tiene FFI a través de funciones de devolución de llamada de JavaScript para acceder a los métodos y propiedades de las funciones nativas del teléfono móvil, incluidos acelerómetro, cámara (también PhotoLibrary y SavedPhotoAlbum), brújula, almacenamiento (base de datos SQL y almacenamiento local), notificación, medios y captura (reproducción y grabación o audio y video), Archivo, Contactos (libreta de direcciones), Eventos, Información del dispositivo y de la conexión. [1] , [2] .
  • Wolfram Language proporciona una tecnología llamada WSTP (Wolfram Symbolic Transfer Protocol) que permite la llamada bidireccional de código entre otros lenguajes con enlaces para C ++, Java, .NET y otros lenguajes.
  • Zig proporciona FFI ac usando la cImportfunción incorporada . [19]

Además, muchas FFI se pueden generar automáticamente: por ejemplo, SWIG . Sin embargo, en el caso de un lenguaje de extensión, puede ocurrir una inversión semántica de la relación entre el huésped y el anfitrión, cuando un cuerpo más pequeño de lenguaje de extensión es el invitado que invoca servicios en el cuerpo más grande del lenguaje del anfitrión, como escribir un pequeño complemento [20 ] para GIMP. [21]

Algunas FFI están restringidas a funciones independientes , mientras que otras también permiten llamadas de funciones integradas en un objeto o clase (a menudo llamadas llamadas a métodos ); algunos incluso permiten la migración de tipos de datos y / u objetos complejos a través del límite del lenguaje.

En la mayoría de los casos, una FFI se define mediante un lenguaje de "nivel superior", de modo que puede emplear servicios definidos e implementados en un lenguaje de nivel inferior, normalmente un lenguaje de sistemas como C o C ++ . Por lo general, esto se hace para acceder a los servicios del SO en el idioma en el que se define la API del SO o por consideraciones de rendimiento.

Muchas FFI también proporcionan los medios para que el idioma llamado invoque servicios en el idioma anfitrión.

El término interfaz de función extranjera generalmente no se usa para describir tiempos de ejecución multilingües como Microsoft Common Language Runtime , donde se proporciona un "sustrato" común que permite que cualquier lenguaje compatible con CLR use servicios definidos en cualquier otro. (Sin embargo, en este caso, CLR incluye un FFI, P / Invoke , para llamar fuera del tiempo de ejecución). Además, muchas arquitecturas de computación distribuida como la invocación de método remoto de Java (RMI), RPC, CORBA , SOAP y D- Los autobuses permiten que los diferentes servicios se escriban en diferentes idiomas; estas arquitecturas generalmente no se consideran FFI.

Casos especiales [ editar ]

Hay algunos casos especiales, en los que los lenguajes se compilan en la misma máquina virtual de código de bytes, como Clojure y Java , así como Elixir y Erlang . Dado que no hay interfaz, no es una FFI, estrictamente hablando, mientras que ofrece la misma funcionalidad al usuario.

Ver también [ editar ]

  • Interoperabilidad lingüística
  • Lenguaje de definición de interfaz
  • Convención de llamadas
  • Destrozar nombre
  • Interfaz de programación de aplicaciones
  • Interfaz binaria de la aplicación
  • Comparación de máquinas virtuales de aplicaciones
  • TRAGO
  • Llamada a procedimiento remoto
  • libffi

Referencias [ editar ]

  1. ^ "Manual de usuario de CFFI" . common-lisp.org . Consultado el 18 de junio de 2015 .
  2. ^ "Introducción a FFI" . HaskellWiki . Consultado el 19 de junio de 2015 . El FFI de Haskell se usa para llamar a funciones desde otros lenguajes (básicamente C en este punto) y para que C llame a funciones de Haskell.
  3. ^ "Documentación de CFFI" . Consultado el 19 de junio de 2015 . Interfaz de función externa C para Python. El objetivo es proporcionar una forma conveniente y confiable de llamar a código C compilado desde Python utilizando declaraciones de interfaz escritas en C.
  4. ^ "Interfaz a otros idiomas" . Adaic.org . Consultado el 29 de septiembre de 2013 .
  5. ^ "Exportación extranjera" . Consultado el 25 de mayo de 2020 .
  6. ^ "Llamar a C desde limpio" . Consultado el 25 de abril de 2018 .
  7. ^ "dardo: biblioteca ffi" . Consultado el 1 de enero de 2020 .
  8. ^ " wiki de la etiqueta ' fortran-iso-c-binding'" . Desbordamiento de pila .
  9. ^ "cgo - El lenguaje de programación Go" . Consultado el 23 de agosto de 2015 .
  10. ^ "Llamar a C y código Fortran · El lenguaje de Julia" . docs.julialang.org . Consultado el 11 de febrero de 2018 .
  11. ^ PyCall.jl: paquete para llamar a funciones de Python desde el lenguaje Julia , JuliaPy, 2018-02-08 , recuperado 2018-02-11
  12. ^ "PHP: FFI - Manual" . El Grupo PHP . Consultado el 13 de junio de 2019 .
  13. ^ Eli Barzilay. "La interfaz extranjera de la raqueta" . Docs.racket-lang.org . Consultado el 29 de septiembre de 2013 .
  14. ^ "TR600.pdf" (PDF) . Consultado el 29 de septiembre de 2013 .
  15. ^ "Implementaciones en línea" . Consultado el 15 de agosto de 2017 .
  16. ^ "Llamada nativa" . Consultado el 15 de agosto de 2017 .
  17. ^ "Uso de funciones externas para llamar a código externo" . Consultado el 1 de junio de 2019 .
  18. ^ Mike Pall. "Biblioteca FFI" . Luajit.org . Consultado el 29 de septiembre de 2013 .
  19. ^ "Importar desde archivo de encabezado C" . Fundación Zig Software . Consultado el 11 de marzo de 2021 .
  20. ^ "4. Un script de muestra" . Gimp.org. 2001-02-04 . Consultado el 29 de septiembre de 2013 .
  21. ^ "Script-Fu y complementos para The GIMP" . Gimp.org . Consultado el 29 de septiembre de 2013 .

Enlaces externos [ editar ]

  • c2.com: interfaz de función externa
  • Interfaz de función ajena Haskell 98
  • Allegro Common Lisp FFI
  • Un generador de interfaz de función ajena para occam-pi
  • UFFI: Interfaz de función externa universal Lisp
  • CFFI: Interfaz de función externa común, para Common Lisp
  • Interfaz nativa de Java: Guía y especificaciones del programador
  • La especificación JNI
  • JSNI (interfaz nativa de JavaScript)
  • biblioteca dyncall que utiliza núcleos de llamadas de ensamblado para una variedad de procesadores, sistemas operativos y convenciones de llamadas
  • FFCALL
  • C / Invocar
  • libffi