如何编写可以从(几乎)任何编程语言调用的一组函数?


33

我想找到一种编写可以通过语言绑定(或其他框架)从任何其他编程语言访问的API的方法。是否有可能做到这一点?如果是这样,哪种编程语言最适合编写“跨语言” API?我的目标是创建可以从正在使用的任何编程语言中访问的一组函数,这样就无需手动以每种语言重新编写整个API。


4
如果您出于市场原因只能说“我们支持一切”,则可以只用C语言编写一个低级DLL或共享库。如果您希望Java中的任何人使用您的东西,更好地提供Java接口。
mjfgates 2012年

1
您说“(几乎)任何”,为此您将排除哪些语言?还是哪个对您来说最重要?
funkybro

22
网络服务?您可以在php中编写一些功能。几乎任何一种语言都可以与网页进行交互,提供参数并读取结果。
Pieter B

7
+1是因为这是一个有趣的问题-但通过说出为什么要这样做可以改善您的问题。你的目标是什么?
TarkaDaal 2012年

@PieterB =>回答。
康拉德·鲁道夫2012年

Answers:


44

您有几种选择:

  1. 创建一个HTTP接口,几乎所有内容都可以使用HTTP,从而可以使用多种语言。

  2. 创建可以链接到语言运行时的内容,这将非常耗时,因为您需要找到一种将其连接到许多不同语言的方法。


具体来说,您打算使用哪种HTTP接口?
安德森·格林

@AndersonGreen没关系(因为任何可以打开网络套接字的语言都可以说HTTP),但是REST是有用的伪标准。
恢复莫妮卡

7
REST + JSON将是一个合理的解决方案
David Hayes 2012年

我也同意,使用HTTP进行通信可以使几乎每种语言与应用程序的功能进行交互。
这里只有玻利维亚人

30

我认为C或C ++最适合您的目的。您可以使用SWIG(简化包装程序和接口生成器)从C或C ++ API生成语言绑定。

SWIG是一种软件开发工具,可将用C和C ++编写的程序与各种高级编程语言相连接。SWIG与不同类型的目标语言一起使用,包括诸如Perl,PHP,Python,Tcl和Ruby之类的通用脚本语言。支持的语言列表还包括非脚本语言,例如C#,Common Lisp(CLISP,Allegro CL,CFFI,UFFI),D,Go语言,Java(包括Android),Lua,Modula-3,OCAML,Octave和R。还有几种解释和编译的Scheme支持的实现(Guile,MzScheme / Racket,Chicken)。SWIG最常用于创建高级解释或编译的编程环境,用户界面,以及作为测试和原型C / C ++软件的工具。SWIG通常用于解析C / C ++接口并生成上述目标语言调用C / C ++代码所需的“胶水代码”。SWIG还可以XML和Lisp s表达式的形式导出其解析树。SWIG是免费软件,SWIG生成的代码与商业和非商业项目兼容...


32
C ++是一个糟糕的选择。它有很多问题:对运行时库的依赖,未指定的ABI(尤其是重整)等。从C ++头生成绑定非常棘手。SWIG是相当有限的事情。查看所有复杂的基础设施,例如Python Qt绑定。
SK-logic

14
@ SK-logic:并非如此。C需要像C ++一样的运行时库。ABI可以通过C ++进行控制,extern "C"因此在外部与C兼容。因此,您确实具有C ++的内部优势(较高的类型安全性,库),但是具有C的优势(事实上的ABI标准)
MSalters 2012年

3
@ SK-logic未指定的ABI只是一个已解决的问题,请参阅SWIG,Boost.Python和许多其他语言绑定。
康拉德·鲁道夫

3
@MSalters不会忘记异常以及它们跨库边界的普遍不工作性
sehe 2012年

3
-1为C ++建议。C很容易,C ++会使事情变得不必要。
欧内斯特·弗里德曼·希尔

23

几乎有2种方法:

  • C API。几乎任何一种语言都将加载C库并调用其函数。您如何执行此操作取决于源语言。
  • 某种RPC机制。这可以是通过HTTP运行的REST API,也可以是通过套接字运行的二进制接口。除非您寻求最低的公分母机制(例如套接字),否则您将面临没有客户端访问例程的风险(例如,某些语言没有正确的SOAP客户端来调用使用SOAP实现的API,或者存在互操作性问题)。坚持使用最简单的HTTP / REST接口或套接字。套接字的优点是,它们不需要HTTP服务器即可将接口公开给客户端,并且可以更轻松地与客户端在同一服务器上运行,并具有更好的性能。

进行此更改所需的工作取决于所使用的系统,例如,套接字接口可以工作,但是与http库相比,客户端库往往更底层。

您可以尝试找到一个支持所有要使用的语言的网络库,并根据该库实现API-例如,使用ZeroMQ可为您提供很大的灵活性,因此您可以使用ZeroMQ接口编写API,并且那么任何想要调用您的API的语言都必​​须使用ZeroMQ客户端库来执行此操作。选择一个支持多种语言的库,并允许您进行进程内和进程外通信以实现最佳性能。


那么,如果我也想用多种语言编写API,我需要采取什么步骤?(就我而言,这些语言将是Javascript,C ++和Java。)
Anderson Green

我应该为每种语言编写3个单独的RESTful API吗?
安德森·格林

您用每种语言编写了一个本地包装程序,以处理加载和调用基础C dll。或用C ++编写并使用SWIG为您完成。如果您使用的是REST API,则同样适用,可以先编写一个API,然后再编写3个包装器,但是如果您要编写REST API,则每种语言都可以直接调用REST API-不必打扰用包装纸。
gbjbaanb 2012年

dll(动态链接库)是否可以与Windows以外的任何平台兼容?我需要这里的跨平台兼容性。
安德森·格林

不,您需要为其他平台重新编译它。例如,Linux使用.so而不是.dll。只需要直接重新编译,无需(或非常小的)代码更改。
gbjbaanb 2012年

12

如果性能和呼叫延迟不是问题,请考虑提供一个全面的命令行界面(可能在其顶部使用脚本语言)。ImageMagick可能是此类“ API”的一个很好的例子。另一个很好的例子是Tk工具箱。


您将推荐使用哪种脚本语言和/或编程语言来创建命令行外部功能界面?另外,您是否找到了此类接口的任何具体示例?
安德森·格林

@AndersonGreen,任何具有不错的元编程语言都可以达到这种目的。例如,Scheme,MetaLua,其他各种可嵌入Lisps,Tcl。您也可以轻松实现自己的命令语言。许多CAD / CAE系统都以这种方式运行。已经提到的Tk是另一个典型示例。
SK-logic

为了以这种方式使用命令行界面,您是要获取特定命令的控制台输出(例如whoami在Ubuntu上获取用户名),还是有其他想法?
安德森·格林

@AndersonGreen,在大多数情况下用管道输送stdin和stdout就足够了。
SK-logic

5

API到底是什么意思?

在许多平台上,您都可以链接到DLL或类似的结构,但是是否需要为特定的本机目标(Intel / ARM)或字节序重新编译?由于数据类型问题或构造(指针试图返回不支持它们的语言),特定的二进制接口对于某些语言可能仍然会遇到困难,因此您还必须考虑API本身的设计,以免排除某些语言或从这些语言中繁琐地使用它。

诸如C之类的可移植性以及基于DLL中二进制端点的接口可能很好,并且通常可以在大多数平台和大多数语言上调用,但是可能需要以不同的方式进行编译和/或以不同的方式提供或链接到不同的静态库。

在我看来,在您提供有关API公开的平台/服务的更多信息之前,选择编写库或服务的语言或按照定义定义的语言并不是问题的本质。如果您可以假定网络堆栈可用并且不要求直接链接的函数调用级别的性能,则该API可以轻松地基于HTTP并使用某种客户端语言的填充程序,以使请求透明。

我认为通常来说,这个问题过于笼统,无法在现实世界中使用,因为鉴于所提供的服务类型,您没有给出关于哪种API可能适用的指示。


2

要添加到以上建议使用RPC机制的答案中。您可以使用Apache Thrift。(http://thrift.apache.org/)。它基本上是一个RPC框架。

根据Thrift Wiki:

用于可扩展的跨语言服务开发的Apache Thrift软件框架将软件堆栈与代码生成引擎结合在一起,以构建可在C ++,Java,Python,PHP,Ruby,Erlang,Perl,Haskell,C#,可可,JavaScript,Node.js,Smalltalk,OCaml和Delphi等语言


如何使用Apache Thrift完成外部函数调用?
安德森·格林

0

用任何语言写出一个文本文件,该函数具有调用要传递的参数的功能。让您的“我与任何人”应用程序监视目录,一旦看到process-call.txt,它就会开始工作。没有服务器或网络协议;甚至非计算机语言方法也可以初始化功能。甚至一个人也可以创建文本文件。

内容可能如下所示:

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

;)您可能会永远等待获得答案。您只需要向其他进程发送一些字节,但是我敢肯定这不是整个规范。


当您只有命令行界面+ stdin / stdout时,似乎过于复杂。
恢复莫妮卡2012年

1
布伦丹,甚至更好的电话可以++ 1。我从没看过它的作用,但曾几何时,人们在卡上打孔以传输字节。
Pareshkumar 2012年

4
这是个笑话吧?我们不在这里做。
欧内斯特·弗里德曼·希尔

fdisk和/ root部分是个玩笑,但是我作为平台研发人员(开发人员和分析师)参与了超过5年,以创建一个平台产品,并产生了上千万美元的收益。它使用这种类型的REST方法为客户端吐出了数百万个可运输的物理(非pdf和电子邮件)项目(每个项目处理文件的大小在数百MB之内)。我们的主要系统triolgy-SAP-MS Office-PLC Drivewrs-PDF Workflow相互配合,并且与纯旧的UTF-8文本文件以及zip内含zip和zip内的zip一起工作良好,并且没有HTTP bs开销。
Pareshkumar

我可以问个问题吗?为什么没有人认为JSON是个玩笑?我的建议有何不同?我们可能已经使用过json,但它并不是在2003年左右出现的。XML太胖了,但是那时候是当月的味道,而不是最实用,最简单的灵魂。
Pareshkumar

0

OpenGL是描述内容的一个很好的例子-它是用C编写的API,其设计方式易于编写其他语言的绑定

  1. 可以从大多数编程语言(通常是编译后的扩展或PyPy ctypes库等之类)中调用C库。

  2. 所有函数都将简单数据类型作为参数(布尔值,整数,浮点数,常量,数组),因为带有指针的函数可能难以翻译成某些语言

  3. 拥有自己的数字数据类型,用于指定精度和带符号的“性”(而其他int float方面可能有所不同)

如果仅针对C用户,则生成的API不一定是您可以编写的使用最好的C API。但是,这意味着这些功能几乎可以直接暴露给另一种语言(例如,PyOpenGL文档列出了差异,其中大多数差异很小)

在这个冗长的API之上,您可以围绕此(游戏框架等)编写更多的“对开发者友好”的包装器

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.