Buitenlandse functie-interface - Foreign function interface
Een buitenlandse functie-interface ( FFI ) is een mechanisme waardoor een programma geschreven in een programmeertaal kunnen routines of gebruik maken van de voorzieningen die zijn geschreven in een ander noemen.
naamgeving
De term komt van de specificatie voor Common Lisp , die expliciet verwijst naar de taalfuncties voor inter-taalgesprekken als zodanig; de term wordt ook officieel gebruikt door de programmeertalen Haskell , Rust en Python . Andere talen gebruiken andere terminologie: de programmeertaal Ada spreekt over " taalbindingen ", terwijl Java naar zijn FFI verwijst als de JNI ( Java Native Interface ) of JNA ( Java Native Access ). De interface voor buitenlandse functies is een algemene terminologie geworden voor mechanismen die dergelijke diensten leveren.
Operatie
De primaire functie van een buitenlandse functie interface is de semantiek en stuurman bellen conventies van een programmeertaal (de host- taal, of de taal die de FFI definieert), met de semantiek en conventies van een ander (de gast taal). Dit proces moet ook rekening houden met de runtime-omgevingen en/of de binaire applicatie-interfaces van beide. Dit kan op verschillende manieren:
- Vereisen dat gasttaalfuncties die in de hosttaal kunnen worden opgeroepen, op een bepaalde manier worden gespecificeerd of geïmplementeerd, vaak met behulp van een of andere compatibiliteitsbibliotheek.
- Gebruik van een tool om gasttaalfuncties automatisch te "verpakken" met de juiste lijmcode , die elke noodzakelijke vertaling uitvoert.
- Gebruik van wrapperbibliotheken
- Beperking van de reeks hosttaalmogelijkheden die in meerdere talen kunnen worden gebruikt. C++-functies die vanuit C worden aangeroepen, mogen bijvoorbeeld (in het algemeen) geen referentieparameters of worpuitzonderingen bevatten.
FFI's kunnen worden bemoeilijkt door de volgende overwegingen:
- Als de ene taal garbage collection (GC) ondersteunt en de andere niet; er moet voor worden gezorgd dat de niet-GC-taalcode niets doet om GC in de andere te laten mislukken. In JNI bijvoorbeeld moet C-code die objectverwijzingen "vasthoudt" die het van Java ontvangt, dit feit "registreren" bij de Java-runtime-omgeving (JRE); anders kan Java objecten verwijderen voordat C ermee klaar is. (De C-code moet ook expliciet de link naar een dergelijk object vrijgeven zodra C dat object niet meer nodig heeft.)
- Ingewikkelde of niet-triviale objecten of datatypes kunnen moeilijk van de ene naar de andere omgeving in kaart worden gebracht.
- Het is misschien niet mogelijk voor beide talen om verwijzingen naar hetzelfde exemplaar van een veranderlijk object te behouden, vanwege het bovenstaande toewijzingsprobleem.
- Een of beide talen kunnen draaien op een virtuele machine (VM); bovendien, als beide zijn, zullen dit waarschijnlijk verschillende VM's zijn.
- Taaloverschrijdende overerving en andere verschillen, zoals tussen typesystemen of tussen object-preparaat modellen , kan bijzonder moeilijk zijn.
op taal
Voorbeelden van FFI's zijn:
- Ada- taalbindingen, waardoor niet alleen buitenlandse functies kunnen worden aangeroepen, maar ook de functies en methoden kunnen worden geëxporteerd die vanuit niet-Ada-code kunnen worden aangeroepen.
- C++ heeft een triviale FFI met C , omdat de talen een significante gemeenschappelijke subset delen. Het primaire effect van de externe "C" -declaratie in C++ is het uitschakelen van C++- naammanipulatie .
- Clean biedt een bidirectionele FFI met alle talen volgens C of de stdcall-aanroepconventie .
- CNI , alternatief voor JNI gebruikt in de GNU-compileromgeving.
- D doet het op dezelfde manier als C++ , met extern "C" via extern (C++)
- Dart bevat dart:ffi-bibliotheek om native C- code aan te roepen voor mobiele, opdrachtregel- en servertoepassingen
- Dynamische talen , zoals Python , Perl , Tcl en Ruby , bieden allemaal gemakkelijke toegang tot native code die is geschreven in C/C++ (of een andere taal die voldoet aan de C/C++-aanroepconventies).
- Factor heeft FFI's voor C, Fortran , Objective-C en Windows COM ; al deze maken het mogelijk om willekeurige gedeelde bibliotheken dynamisch te importeren en aan te roepen.
- De FFI's van Common Lisp en Haskell
- Fortran 2003 heeft een module ISO_C_BINDING die interoperabele datatypes biedt (zowel intrinsieke types als POD-structuren), interoperabele pointers, interoperabele globale datastores en mechanismen voor het aanroepen van C vanuit Fortran en voor het aanroepen van Fortran vanuit C. Het is verbeterd in de Fortran 2018 standaard.
-
Go kan C-code direct bellen via het
"C"pseudo-pakket. - GWT , waarin Java is gecompileerd naar JavaScript, heeft een FFI genaamd JSNI waarmee de Java-bron willekeurige JavaScript-functies kan aanroepen en JavaScript kan terugbellen naar Java.
- JNI , dat een interface biedt tussen Java en C/C++, de geprefereerde systeemtalen op de meeste systemen waarop Java wordt geïmplementeerd. JNA biedt een interface met native bibliotheken zonder lijmcode te hoeven schrijven . Een ander voorbeeld is JNR
- Nim heeft een FFI waarmee het de broncode van C , C++ en Objective-C kan gebruiken . Het kan ook communiceren met Javascript.
-
Julia heeft een
ccallsleutelwoord om C te bellen (en andere talen, bijvoorbeeld Fortran); terwijl pakketten, die vergelijkbare no-boilerplate-ondersteuning bieden, beschikbaar zijn voor sommige talen, bijvoorbeeld voor Python (om bijvoorbeeld OO-ondersteuning en GC-ondersteuning te bieden), Java (en ondersteunt andere JDK-talen, zoals Scala) en R. Interactief gebruik met C++ is ook mogelijk met pakket Cxx.jl. - PHP biedt FFI aan C.
- Ruby biedt FFI hetzij via de ffi gem, of via de standaard bibliotheek viool .
require 'fiddle'
libm = Fiddle.dlopen('/lib/libm.so.6')
# Equivalent to: double floor(double x);
floor = Fiddle::Function.new(
libm.sym('floor'), # ptr is a referenced function(, or symbol), of a Fiddle::Handle.
[Fiddle::TYPE_DOUBLE], # args is an Array of arguments, passed to the ptr function.
Fiddle::TYPE_DOUBLE # ret_type is the return type of the function
)
# Equivalent to: floor(3.14159);
floor.call(3.14159) #=> 3.0
-
Python levert de ctypes en cffi- modules. De ctypes-module kan bijvoorbeeld C-functies uit gedeelde bibliotheken / DLL's on-the-fly laden en eenvoudige gegevenstypen automatisch als volgt tussen Python- en C-semantiek vertalen:
import ctypes libc = ctypes.CDLL('/lib/libc.so.6') # Under Linux/Unix t = libc.time(None) # Equivalent C code: t = time(NULL) print(t)
- P/Invoke , dat een interface biedt tussen Microsoft Common Language Runtime en native code.
- Racket heeft een native FFI die sterk is gebaseerd op macro's, waarmee willekeurig gedeelde bibliotheken dynamisch kunnen worden geïmporteerd.
- Raku kan Ruby , Python , Perl , Brainfuck , Lua , C , C++ , Go en Scheme Guile / Gambit noemen
- Rust definieert ook een interface voor buitenlandse functies.
- Visual Basic heeft een declaratieve syntaxis waarmee het niet-Unicode C-functies kan aanroepen.
- Een van de basissen van het Component Object Model is een gemeenschappelijke interface-indeling, die native dezelfde typen gebruikt als Visual Basic voor strings en arrays.
- LuaJIT, een just-in-time implementatie van Lua , heeft een FFI die het mogelijk maakt om "externe C-functies aan te roepen en C-gegevensstructuren te gebruiken uit pure Lua-code".
- PhoneGap (werd genoemd onder de naam Apache Callback, maar nu Apache Cordova) is een platform voor het bouwen van native mobiele applicaties met HTML, CSS en JavaScript. Heeft daarnaast FFI's via JavaScript-callback-functies voor toegang tot methoden en eigenschappen van de native functies van mobiele telefoons, waaronder Accelerometer, Camera (ook PhotoLibrary en SavedPhotoAlbum), Compass, Storage (SQL-database en localStorage), Notification, Media en Capture (afspelen en opnemen of audio en video), Bestand, Contacten (adresboek), Gebeurtenissen, Apparaat- en Verbindingsinformatie. [1] , [2] .
- Wolfram Language biedt een technologie genaamd WSTP (Wolfram Symbolic Transfer Protocol) die bidirectionele aanroep van code tussen andere talen mogelijk maakt met bindingen voor C++, Java, .NET en andere talen.
-
Zig biedt FFI naar c met behulp van de ingebouwde
cImportfunctie.
Bovendien kunnen veel FFI's automatisch worden gegenereerd: bijvoorbeeld SWIG . In het geval van een extensietaal kan echter een semantische inversie van de relatie tussen gast en host optreden, wanneer een kleinere extensietaal de gast is die services aanroept in de grotere hoeveelheid hosttaal, zoals het schrijven van een kleine plug-in voor GIMP .
Sommige FFI zijn beperkt tot vrijstaande functies , terwijl anderen ook oproepen van functies ingebed in een object of klasse (vaak genoemd toestaan methode gesprekken ); sommige laten zelfs migratie van complexe datatypes en/of objecten over de taalgrens toe.
In de meeste gevallen wordt een FFI gedefinieerd door een taal van een "hoger niveau", zodat het diensten kan gebruiken die zijn gedefinieerd en geïmplementeerd in een taal op een lager niveau, meestal een systeemtaal zoals C of C++ . Dit wordt meestal gedaan om toegang te krijgen tot OS-services in de taal waarin de API van het besturingssysteem is gedefinieerd, of om prestatieoverwegingen.
Veel FFI's bieden ook de middelen voor de opgeroepen taal om ook diensten in de gasttaal aan te roepen.
De term interface voor buitenlandse functies wordt over het algemeen niet gebruikt om meertalige runtimes te beschrijven, zoals de Microsoft Common Language Runtime , waar een gemeenschappelijk "substraat" wordt geleverd waarmee elke CLR-compatibele taal services kan gebruiken die in een andere zijn gedefinieerd. (In dit geval bevat de CLR echter wel een FFI, P/Invoke , om buiten de runtime aan te roepen.) Daarnaast zijn veel gedistribueerde computerarchitecturen zoals de Java Remote Method Invocation (RMI), RPC, CORBA , SOAP en D- Bus staat toe dat verschillende diensten in verschillende talen worden geschreven; dergelijke architecturen worden over het algemeen niet als FFI's beschouwd.
Speciale gevallen
Er zijn enkele speciale gevallen waarin de talen worden gecompileerd in dezelfde bytecode-VM, zoals Clojure en Java , evenals Elixir en Erlang . Omdat er geen interface is, is het strikt genomen geen FFI, terwijl het dezelfde functionaliteit biedt aan de gebruiker.
Zie ook
- Interoperabiliteit tussen talen
- Interfacedefinitietaal
- Oproepconventie
- Naam mangelen
- Applicatie programmeerinterface
- Toepassing binaire interface
- Vergelijking van virtuele applicatiemachines
- SLOK
- Op afstand gemaakt telefoongesperk
- libffi
Referenties
Externe links
- c2.com: interface voor buitenlandse functies
- Haskell 98 buitenlandse functie-interface
- Allegro Common Lisp FFI
- Een Foreign Function Interface-generator voor occam-pi
- UFFI: Lisp Universal Foreign Function Interface
- CFFI: Common Foreign Function Interface, voor Common Lisp
- Java Native Interface: Programmer's Guide en Specificatie
- De JNI-specificatie:
- JSNI (JavaScript Native Interface)
- dyncall-bibliotheek met behulp van assembly-aanroep-kernels voor een verscheidenheid aan processors, besturingssystemen en aanroepconventies
- FFCALL
- C/Invoke
- libffi