脚本语言与c/c++库之间调用的原理是什么?
不同语言之间的调用通信是很多的,以脚本语言调用c++为例,如果是两个独立不同的进程,那采用进程间通信的方式可以传递数据。但如果是c++库呢?比如nodejs底层就会调用c++模块,或者可以调用第三方c++库。调用方法也就是具体怎么操作我实验过,但是更底层的原理,比如nodejs到到底是怎么调用c++的,就不太清楚了,有能讨论或者解答一下的么?
上面的答案很多都是说的通俗表面的道理,但其实我是想知道一些底层调用的原理。最近看到一篇文章里的说法我觉得比较清楚以python调用c库为例说明:
为了实现调用C函数,Python解释器需要做:
(1)找到函数所处的位置:这个意味着在C编译器编译成的二进制文件中寻找这个函数。(2)在可执行的内存中,载入有关这个函数的相关代码。(3)在调用这个函数前,将Python的参数转换为C兼容的参数。(4)用正确的方式调用这个函数。(5)将C函数的返回值转换成Python兼容的变量并将其返回至python代码中。
refGlibGObject
Node.js调用C有两种方式。一种方式是原生模块,这是常规方式。就是一个DLL库,编程的时候按照Node.js的约定,编写特定形式的接口函数,并includenode.js的头文件,并和node.js提供的一些文件一起编译。这样的DLL会导出特定的函数。node.js动态加载DLL,通过特定的函数得到模块支持的方法,然后调用那些方法,传递的参数也是V8引擎定义的JS类对象。因为用了类,必须是C++编写,但是可以作为封装层,封装别的C库。Node.js自带的文件系统访问模块等都是这样的。第二种方式就是第三方DLL。没有按照约定的方式编写,比如Windows的系统DLL。需要Node-FFI。FFI是一种跨语言调用技术,很多脚本语言都有自己的实现。原理就是根据代码中声明的C函数定义,动态生成机器指令,模拟C的函数压栈、弹栈过程。因为V8引擎正好是支持JIT即时编译的,所以很容易实现。这种方式缺点就是因为是没有编译器检查的,所以如果函数声明不对了,可能会导致程序崩溃。