Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何将一种语言(例如python)绑定到另一种语言(例如C+;+;)上?_Java_Python_Binding - Fatal编程技术网

Java 如何将一种语言(例如python)绑定到另一种语言(例如C+;+;)上?

Java 如何将一种语言(例如python)绑定到另一种语言(例如C+;+;)上?,java,python,binding,Java,Python,Binding,我远非python专家,但我经常听到这篇关于C/C++绑定的文章。这个概念是如何工作的,Python(和Java)是如何绑定到基于C的API(如OpenGL)的?这些东西对我来说一直是个谜。通常这些语言都有一种加载用C编写的扩展的方法。Java接口称为JNI(Java本机接口)。Python对其扩展接口有全面的了解 < Python的另一个选项是允许您使用动态可加载C库而不必编写自定义扩展代码的模块。 Perl,有两种调用C++子程序的方法: (另请参阅)-允许通过将C代码编译成可从Perl使

我远非python专家,但我经常听到这篇关于C/C++绑定的文章。这个概念是如何工作的,Python(和Java)是如何绑定到基于C的API(如OpenGL)的?这些东西对我来说一直是个谜。

通常这些语言都有一种加载用C编写的扩展的方法。Java接口称为JNI(Java本机接口)。Python对其扩展接口有全面的了解


< Python的另一个选项是允许您使用动态可加载C库而不必编写自定义扩展代码的模块。

Perl,有两种调用C++子程序的方法:

  • (另请参阅)-允许通过将C代码编译成可从Perl使用的模块,从Perl调用其他语言(主要是但不限于C)的子例程

  • > P>是一种软件开发工具,它将C和C++中的程序与各种高级/脚本语言(包括Perl、PHP、Python、Tcl和露比)连接起来(尽管Syg的起源是用Python绑定)。p> ,如果你有兴趣了解引擎盖下发生了什么


将c/c++与python集成基本上有两种方法:

  • 扩展:从python访问c/c++
  • 嵌入:从c/c访问python解释器++
你提到的是第一个案例。它通常通过编写包装器函数来实现,包装器函数充当不同语言之间的粘合代码,转换函数参数和数据类型以匹配所需的语言。通常使用名为的工具生成此粘合代码。

有关详细的解释,请参见此。

用C89编写的带反射的口译员,谁知道呢?
我感觉您在寻找对该机制的解释,而不是API的链接或关于如何编码的说明。所以,据我所知

主解释器通常是用C编写的,并且是动态链接的。在动态链接的环境中,即使是C89也有一定的反射行为。特别是,
dlopen(3)
dlsym(3)
调用将加载动态(通常为ELF)库,并查找由字符串命名的符号的地址。给出那个地址,解释器可以调用一个函数。即使是静态链接,解释器也可以知道其名称被编译到其中的C函数的地址

因此,只需让解释后的代码告诉解释器调用特定本机库中的特定本机函数即可

该机构可以是模块化的。用脚本编写的解释器扩展库本身可以调用
dlopen(3)
dlsym(3)
的裸钩子,并连接到解释器不知道的新库

对于按值传递简单对象,一些原型函数通常允许各种调用。但是对于结构化数据对象(想象stat(2)),包装器模块需要知道数据的布局。在某些情况下,无论是打包扩展模块还是安装扩展模块,C接口模块都包含相应的头文件,并与手写代码一起构造接口对象。这就是为什么您可能需要安装类似于
libsqlite3 dev
的东西,即使您的系统上已经安装了
sqlite3
;只有
-dev
包具有重新编译链接代码所需的.h文件


我想我们可以这样总结:“这是用暴力和无知完成的。”——)

下面的概念可以相对容易地概括,但是为了清晰起见,我将特别提到C和Python

从Python调用C

这是可行的,因为大多数低级语言/体系结构/操作系统都有定义良好的应用程序二进制接口,这些接口指定了应用程序如何相互交互以及如何与操作系统交互的所有低级细节。这里以x86-64(AMD64)的ABI为例:。它指定了所有细节,比如调用函数的约定和针对C对象文件的链接

有了这些信息,语言实现者就可以

  • 实现语言的ABI 你想打电话给我吗

  • 通过提供一个接口 语言/库以访问 实施

  • (1) 实际上在大多数语言中几乎都是免费的,因为它们的解释器/编译器都是用C编码的,这显然支持C ABI:)。这也是为什么从非C语言编码的语言实现中调用C代码会有困难的原因,例如IronPython(C#中的Python实现)和PyPy(Python中的Python实现)对调用C代码没有特别好的支持,尽管我相信IronPython中在这方面已经做了一些工作

    为了使这一点具体化,我们假设我们有CPython(Python的标准实现,用C语言完成)。我们免费获得(1),因为我们的解释器是用C编写的,我们可以从解释器访问C库,就像从任何其他C程序(dlopen、LoadLibrary等)访问C库一样。现在,我们需要为用我们的语言书写的人提供一种访问这些设施的方式。Python通过or实现这一点。每当程序员使用这些API编写代码时,我们都可以执行适当的库加载/调用代码来调用库

    从C调用Python

    这个方向实际上更容易解释。继续上一个例子,我们的解释器,CPython只不过是一个用C编写的程序,因此它可以导出函数,并作为库进行编译/被我们想用C编写的任何程序链接。CPython导出一组C函数用于访问/运行Python程序,我们可以调用这些函数
    PyObject* PyRun_StringFlags(const char *str, int start, PyObject *globals, PyObject *locals, PyCompilerFlags *flags)¶