Come posso scrivere una serie di funzioni che possono essere invocate da (quasi) qualsiasi linguaggio di programmazione?


33

Mi piacerebbe trovare un modo per scrivere un'API a cui è possibile accedere da qualsiasi altro linguaggio di programmazione tramite collegamenti linguistici (o qualche altro framework). È possibile farlo? In tal caso, quale linguaggio di programmazione sarebbe il più adatto per scrivere un'API "cross-language"? Il mio obiettivo è quello di creare un singolo set di funzioni a cui posso accedere da qualsiasi linguaggio di programmazione con cui sto lavorando, in modo da non dover riscrivere manualmente l'intera API in ogni lingua.


4
Se vuoi solo essere in grado di dire "supportiamo TUTTO" per motivi di marketing, puoi semplicemente scrivere una DLL di basso livello o una libreria condivisa in C.Se vuoi che qualcuno, per esempio, Java, usi il tuo coso, dovresti meglio fornire un'interfaccia Java.
mjfgates,

1
Dici "(quasi) qualsiasi", quali lingue escluderesti a questo scopo? O quali sono i più importanti per te?
funkybro,

22
Servizio web? Puoi scrivere alcune funzioni per esempio in php. Quasi ogni lingua ha la possibilità di interfacciarsi con pagine Web, fornire argomenti e leggere i risultati.
Pieter B,

7
+1 perché è una domanda interessante, ma la tua domanda sarebbe migliorata dicendo perché vuoi farlo. Quali sono i tuoi obiettivi?
TarkaDaal,

@PieterB => risposta.
Konrad Rudolph,

Risposte:


44

Hai alcune opzioni:

  1. Crea un'interfaccia HTTP, quasi tutto può parlare HTTP in modo da ottenere molte lingue.

  2. Crea qualcosa che può essere collegato in un runtime linguistico, questo richiederà piuttosto tempo in quanto dovrai trovare un modo per collegarlo a molte lingue diverse.


Che tipo di interfaccia HTTP hai in mente, in particolare?
Anderson Green,

@AndersonGreen Non dovrebbe importare (dal momento che qualsiasi lingua che può aprire un socket di rete può parlare HTTP), ma REST è un pseudo standard utile.
Ripristina Monica il

7
REST + JSON sarebbe una soluzione ragionevole
David Hayes,

Sono anche d'accordo, l'uso di HTTP per comunicare consente praticamente a tutte le lingue di interagire con le funzioni dell'applicazione.
Solo boliviano qui,

30

Penso che C o C ++ siano i più adatti al tuo scopo. È possibile utilizzare SWIG (Simple Wrapper and Interface Generator) per generare collegamenti linguistici dall'API C o C ++.

SWIG è uno strumento di sviluppo software che collega i programmi scritti in C e C ++ con una varietà di linguaggi di programmazione di alto livello. SWIG viene utilizzato con diversi tipi di lingue di destinazione, inclusi linguaggi di scripting comuni come Perl, PHP, Python, Tcl e Ruby. L'elenco delle lingue supportateinclude anche linguaggi non di scripting come C #, Common Lisp (CLISP, Allegro CL, CFFI, UFFI), D, Go language, Java compreso Android, Lua, Modula-3, OCAML, Octave e R. Anche diversi schemi interpretati e compilati sono supportate implementazioni (Guile, MzScheme / Racket, Chicken). SWIG è più comunemente usato per creare ambienti di programmazione interpretati o compilati di alto livello, interfacce utente e come strumento per testare e prototipare il software C / C ++. SWIG viene in genere utilizzato per analizzare le interfacce C / C ++ e generare il "codice colla" richiesto per le lingue di destinazione sopra indicate per chiamare nel codice C / C ++. SWIG può anche esportare il suo albero di analisi sotto forma di espressioni s-XML e Lisp. SWIG è un software gratuito e il codice generato da SWIG è compatibile con progetti sia commerciali che non commerciali ...


32
Il C ++ sarebbe una scelta terribile. Esistono numerosi problemi: dipendenza da una libreria di runtime, ABI non specificato (in particolare mangling), ecc. La generazione di associazioni dalle intestazioni C ++ è proibitiva in modo proibitivo. SWIG è abbastanza limitato. Guarda tutte le infrastrutture complicate in circolazione, diciamo, i collegamenti Python Qt.
SK-logic,

14
@ SK-logic: non proprio. C ha bisogno di una lib di runtime proprio come C ++. L'ABI può essere controllato in C ++ tramite extern "C"quindi è C-compatibile all'esterno. Quindi, hai i vantaggi interni di C ++ (maggiore sicurezza dei tipi, librerie) ma i vantaggi esterni di C (standard ABI de facto)
MSalter

3
@ SK-logic L'ABI non specificato è semplicemente un problema risolto, vedi SWIG, Boost.Python e una miriade di altri collegamenti linguistici.
Konrad Rudolph,

3
@MSalters non dimentica le eccezioni e la loro non operatività generale oltre i confini della biblioteca
vedi il

3
-1 per il suggerimento C ++. C è facile, C ++ rende le cose inutilmente difficili.
Ernest Friedman-Hill,

23

Ci sono praticamente 2 modi:

  • un'API C. Praticamente ogni linguaggio mai esistito caricherà una libreria C e chiamerà le sue funzioni. Come lo fai dipende dalla lingua di partenza.
  • un meccanismo RPC di qualche tipo. Può essere un'API REST in esecuzione su HTTP o un'interfaccia binaria in esecuzione su un socket. A meno che non si scelga il meccanismo di denominazione comune più basso (ad es. Un socket) si corre il rischio di non avere routine di accesso al client (ad es. Alcune lingue non hanno i client SOAP giusti per chiamare un'API implementata tramite SOAP o ci sono problemi di interoperabilità). Attenersi alla più semplice, un'interfaccia HTTP / REST o un socket. I socket hanno il vantaggio di non avere bisogno di un server HTTP per esporre l'interfaccia ai client e possono essere eseguiti più facilmente sullo stesso server del client con prestazioni migliori.

Il lavoro richiesto per queste modifiche dipende dal sistema utilizzato, ad esempio un'interfaccia socket funzionerà, ma le librerie lato client tendono ad essere di livello più basso rispetto alle librerie http.

Potresti provare a trovare una libreria di rete che supporti tutte le lingue che desideri utilizzare e implementare l'API in termini di tale libreria - ad esempio, l'utilizzo di ZeroMQ ti offre molta flessibilità, quindi scriveresti l'API utilizzando le interfacce ZeroMQ e quindi qualsiasi lingua che desideri chiamare l'API deve utilizzare la libreria client ZeroMQ per farlo. Scegli una libreria che supporti una vasta gamma di lingue e ti permetta di comunicare in-process e out-of-process per ottenere le migliori prestazioni.


Quindi quali passi dovrei prendere se volessi scrivere anche l'API in più lingue? (Nel mio caso, quelle lingue sarebbero Javascript, C ++ e Java.)
Anderson Green

Devo solo scrivere 3 API RESTful separate per ciascuna delle lingue?
Anderson Green,

Scrivi un wrapper nativo in ognuna di queste lingue che gestisce il caricamento e la chiamata alla Cll sottostante. Oppure scrivilo in C ++ e usa SWIG per farlo. Se stai usando un'API REST, lo stesso vale, scrivi una singola API e poi 3 wrapper, ma se stai scrivendo un'API REST, ogni lingua sarà in grado di chiamare direttamente l'API REST - non preoccuparti con un involucro.
gbjbaanb,

La DLL (libreria collegata dinamicamente) sarebbe compatibile con qualsiasi piattaforma oltre a Windows? Ho bisogno di compatibilità multipiattaforma qui.
Anderson Green,

no, dovresti ricompilarlo per altre piattaforme. Linux ad esempio usa .so invece di .dll. È necessaria solo una ricompilazione diretta, nessuna modifica del codice (o molto minore).
gbjbaanb,

12

Se le prestazioni e la latenza delle chiamate non rappresentano un problema, è consigliabile fornire un'interfaccia a riga di comando completa (probabilmente, utilizzando un linguaggio di scripting al di sopra di esso). ImageMagick può essere un buon esempio di tale "API". Un altro buon esempio è Tk toolkit.


Quale linguaggio di scripting e / o linguaggio di programmazione consiglieresti allo scopo di creare un'interfaccia con funzioni esterne da riga di comando? Inoltre, hai trovato esempi concreti di tali interfacce?
Anderson Green,

@AndersonGreen, qualsiasi lingua con metaprogrammazione decente va bene per questo scopo. Ad esempio, Scheme, MetaLua, varie altre Lisps incorporabili, Tcl. Puoi facilmente implementare anche il tuo linguaggio di comando. Molti sistemi CAD / CAE funzionano in questo modo. Un Tk già menzionato è un altro esempio tipico.
SK-logic,

Al fine di utilizzare un'interfaccia a riga di comando in questo modo, otterresti l'output della console per un comando specifico (come whoamisu Ubuntu per ottenere il nome utente) o avevi in ​​mente qualcos'altro?
Anderson Green,

@AndersonGreen, pipdin stdin e stdout dovrebbero essere sufficienti nella maggior parte dei casi.
SK-logic,

5

Per API, cosa intendi esattamente?

Su molte piattaforme potresti collegare una DLL o una costruzione simile, ma dovresti ri-compilare per un determinato target nativo (Intel / ARM) o endianness ancora qualificarsi? Una particolare interfaccia binaria potrebbe avere ancora difficoltà con alcuni linguaggi a causa di problemi o costrutti di tipi di dati (puntatori che cercano di essere restituiti a linguaggi che non li supportano bene), quindi dovresti anche considerare il design dell'API stessa in modo da non per escludere alcune lingue o farne uso ingombrante da quelle lingue.

Qualcosa di portatile come C e un'interfaccia basata su endpoint binari in una DLL potrebbe andare bene e generalmente richiamabile sulla maggior parte delle piattaforme e dalla maggior parte delle lingue, ma potrebbe aver bisogno di essere compilato in modo diverso e / o offerto in diversi gusti o collegato a diverse librerie statiche.

Mi sembra che la scelta della lingua in cui scrivi la tua biblioteca o il tuo servizio o qualsiasi altra cosa, per definizione, non sia intrinseca alla domanda fino a quando non avrai dato di più sulla piattaforma / servizio che l'API espone. Se si può presumere che sia disponibile uno stack di rete e che le prestazioni a livello di chiamata a funzione diretta non siano un requisito, l'API potrebbe facilmente essere basata su HTTP con un qualche tipo di shim per la lingua del client per rendere trasparenti le richieste.

Penso che in generale questa domanda sia eccessivamente ampia per essere utile nel mondo reale, perché non hai dato indicazioni su quale tipo di API potrebbe essere adatta dato il tipo di servizio che viene offerto.


2

Aggiungere alle risposte precedenti che suggeriscono di utilizzare un meccanismo RPC. Potresti usare Apache Thrift. ( Http://thrift.apache.org/ ). È fondamentalmente un framework RPC.

Secondo la wiki di Thrift:

Il framework software Apache Thrift, per lo sviluppo di servizi in più lingue scalabili, combina uno stack software con un motore di generazione di codice per creare servizi che funzionano in modo efficiente e senza soluzione di continuità tra C ++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C #, Cocoa, JavaScript, Node.js, Smalltalk, OCaml e Delphi e altre lingue


In che modo è possibile effettuare chiamate a funzioni esterne utilizzando Apache Thrift?
Anderson Green,

0

Chiedi a qualsiasi lingua di scrivere un file di testo con la funzione da chiamare con i parametri da trasmettere. Fai in modo che la tua app "Vado d'accordo con chiunque" guardi una directory e una volta che vede un processo-call.txt farlo funzionare. Nessun server o protocolli di rete; anche un metodo non linguistico può avviare le funzioni. Anche una persona potrebbe semplicemente creare il file di testo.

Il contenuto potrebbe apparire come:

Call-method:  fdisk()
Params:  (string) "/root", (string) "write-back-file-expected.txt"

;) potresti aspettare per sempre per ottenere una risposta. Devi solo spingere qualche byte nell'altro processo, ma sono sicuro che non è l'intera specifica.


Sembra eccessivamente complicato quando potresti avere solo un'interfaccia a riga di comando + stdin / stdout.
Ripristina Monica il

1
Anche meglio chiamare può ++ 1 che, Brendan. Non l'ho mai visto in azione, ma una volta le persone facevano dei buchi nella carta per trasferire i byte in giro.
Pareshkumar,

4
Questa è una risposta scherzosa, vero? Non lo facciamo qui.
Ernest Friedman-Hill,

Bene, la parte fdisk e / root è una barzelletta, ma io sono stato coinvolto come piattaforma di ricerca e sviluppo (sviluppatore e analista) per oltre 5 anni per creare un prodotto piattaforma che ha prodotto buoni risultati negli anni 10 milioni di dollari. Sputa milioni di elementi fisici (non pdf ed e-mail) shippable per client (con elaborazione di file che vanno in centinaia di MB per articolo) usando questo tipo di metodo REST. Avevamo un grande triolgy di sistema-SAP-MS Office-PLC Drivewrs-PDF Workflow tutti presi l'uno dall'altro e che funzionavano bene insieme con file di testo UTF-8 semplici e vecchi e una zip con-in una zip con-in una zip, e nessun sovraccarico HTTP bs.
Pareshkumar,

Posso fare una domanda? Perché nessuno pensa che JSON sia uno scherzo? In che modo ciò che ho raccomandato è diverso? Avremmo / avremmo potuto usare JSON ma non era in circolazione nel 2003. XML è troppo grasso, ma allora era il sapore del mese, non l'anima più pratica e semplice.
Pareshkumar,

0

OpenGL è un buon esempio di ciò che descrivi: è un'API scritta in C, progettata in un modo per cui è facile scrivere i collegamenti in altre lingue

  1. Le librerie C possono essere chiamate dalla maggior parte dei linguaggi di programmazione (di solito come estensioni compilate o cose come la ctypeslibreria di PyPy ecc.)

  2. Tutte le funzioni accettano tipi di dati semplici come argomenti (booleano, intero, virgola mobile, costanti, matrici), poiché le funzioni che assumono puntatori possono essere scomode da tradurre in alcune lingue

  3. Avere i propri tipi di dati numerici, che specificano la precisione e la firma (mentre int floatetc può differire)

L'API risultante non è necessariamente l'API C più bella da usare che potresti scrivere se si rivolge solo agli utenti C. Tuttavia, significa che le funzioni possono essere esposte quasi direttamente a un'altra lingua (ad esempio i documenti PyOpenGL elencano le differenze, la maggior parte delle quali sono piuttosto minime)

Oltre a questa API dettagliata, puoi scrivere più wrapper "per sviluppatori" attorno a questo (framework di gioco e simili)

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.