外部函数接口 LibFFI

“FFI” 的全名是 Foreign Function Interface,通常指的是允许以一种语言编写的代码调用另一种语言的代码。而 “Libffi” 库只提供了最底层的、与架构相关的、完整的”FFI”,因此在它之上必须有一层来负责管理两种语言之间参数的格式转换。

高级语言编译器产生代码时都会依据一系列的规则,这些规则十分必要,特别是对独立编译来说。其中之一是“调用约定” (Calling Convention),它包含了编译器关于函数入口处的函数参数、函数返回值的一系列假设。它有时也被称作“ABI”(Application Binary Interface)。调用约定(Calling Conventions)定义了程序中调用函数的方式,它决定了在函数调用的时候数据(比如说参数)在堆栈中的组织方式。

通常来说函数调用要用到的两条基本的指令:”CALL”指令和”RET”指令。”CALL”指令将当前的指令指针(这个指针指向紧接在CALL指令后面的那条指令)压入堆栈,然后执行一条无条件转移指令转移到新的代码地址。”RET”是与”CALL”指令配合使用的指令,在绝大多数函数中它是最后一条指令。”RET”指令弹出返回地址(就是早些时候”CALL”指令压入堆栈的地址)并将其加载到”EIP”寄存器中,然后从这个地址开始继续执行。

图1-1 说明调用约定”stdcall”的调用过程,调用时,最末一个参数最先压入堆栈,而由被调用函数使用RET指令清栈。RET指令带有一个操作数,该操作数指明在EIP跳回主要函数之前需要释放的堆栈空间的字节数。这就是说,stdcall调用约定中RET指令带的操作数往往就意味着函数一共传入几个参数。

图1-1 stdcall调用

独立编译时,调用一个函数除了要知道函数的签名外,还要知道其调用约定。比如 Delphi 中调用”Stdcall”的”VC++”的函数,需对调用约定加以声明。

Procedure ShowMess (h :HWND; mess :PChar ); Stdcall; external LibName;

“LibFFI”针对这些不同的调用约定,提供一个高层次的可移植的API,只需调用这些API就可以在运行时进行动态的函数调用。(这种方式和函数指针不同,函数指针比如在编译时就决定了函数的类型,而”libffi”可以在运行时是才决定被调用函数的类型)。有了 libffi ,我们就有可能写出一个通用而且简洁的调用 C 函数的方法。

目前有许多项目都使用了 libff ,包括 ruby,cpython, openjdk,dalvik vm 等等。例如在 Ruby 中,利用 rubyffi (包装了 libffi )可以如此动态地调用一个 dll

介绍内容来自:http://blogs.ejb.cc/archives/1502/libffi-example-of-the-use

http://www.sourceware.org/libffi/
https://github.com/atgreen/libffi
http://www.oschina.net/p/libffi
-----------------------------------------

时间: 2024-11-03 03:26:50

外部函数接口 LibFFI的相关文章

IO端口和IO内存的区别及分别使用的函数接口

每个外设都是通过读写其寄存器来控制的.外设寄存器也称为I/O端口,通常包括:控制寄存器.状态寄存器和数据寄存器三大类.根据访问外设寄存器的不同方式,可以把CPU分成两大类.一类CPU(如M68K,Power PC等)把这些寄存器看作内存的一部分,寄存器参与内存统一编址,访问寄存器就通过访问一般的内存指令进行,所以,这种CPU没有专门用于设备I/O的指令.这就是所谓的"I/O内存"方式.另一类CPU(典型的如X86),将外设的寄存器看成一个独立的地址空间,所以访问内存的指令不能用来访问这

STM32W108无线射频模块外部中断接口应用实例

STM32W108无线射频模块外部中断接口应用实例 编写中断服务程序,响应外部中断,实现通过按键触发中断,然后通过LED显示相应的状态. 1 STM32W108开发环境与硬件说明 硬件:STM32W108 Zigbee开发板.5V 1A电源.J-LINK烧写器.PC机等. 软件:IAR Embedded Workbench开发软件. 为开发板中的按键连接原理图,按键与STM32W108无线模块连接的原理图. 按键连接图 2软件设计与规划 测试程序的流程图如下所示,节点首先初始化硬件,然后注册中断

Java 8 函数接口详细教程

ay = new byte[array.length]; for (int i = 0; i < array.length; i++) { transformedArray[i] = function.applyAsByte(array[i]); } return transformedArray;}1234567这里测试如何实现short数组至byte数组乘以2的转换: short[] array = {(short) 1, (short) 2, (short) 3};byte[] trans

内部函数外部函数

内部函数: 一个函数只能被本文件中其它函数调用,定义时static void fun(char a, char b){}用于多人协作避免同名 外部函数: 默认extern可省,extern void fun(char a, char b){},可为其他文件函数调用,在其他需要调用fun()的文件先声明extern void fun(char a, char b);表示是从其他文件中定义的外部函数

Java 8 中函数接口,陈货翻新了炒,只是为了Lambda表达式

Java开发人员应该对java.lang.Runnable,java.util.Comparator,java.util.concurrent.Callable 等等接口不会感到陌生.他们都只有一个单一的抽象方法.这样的接口,我们通常叫单一抽象方法接口(SAM,Single Abstract Method Interface). 以前大家应该经常使用下面的代码片段 public class InnerAnonymousClassSample { public static void main(S

【E2LSH源码分析】E2LSH函数接口

上一小节,我们对E2LSH代码主要的源码框架和用到的数据结构作了简单介绍(http://blog.csdn.net/jasonding1354/article/details/38331229),这一节我将简单介绍一下E2LSH的主要函数接口. 1.构建R-NN数据结构(定义在NearNeighbors.h) 输入为1-δ.R.d和数据集P,利用下面函数来构建: PRNearNeighborStructT initSelfTunedRNearNeighborWithDataSet(RealT t

如何在 ejs 模板中使用 helper function 外部函数进行特殊处理?

一般我们想要在 ejs 模板中使用外部函数用于特殊的处理,比如:<%= ellipsis(title, 30) %> 通常的做法是: 使用 app.locals 来定义: app.locals.ellipsis = function(str, len) { return str; } // 使用 <%= ellipsis(title, 20) %> 使用 ejs.filters 来定义,详细用法: var ejs = require('ejs'); ejs.filters.elli

c/c++ c中内部函数和外部函数

函数本质上是全局的,因为一个函数要被另外的函数调用,也可以指定函数不能被其他文件调用.根据能否被其他源文件调用,将函数区分为内部和外部函数. 内部函数:(也称静态函数) 只能被本文件中其他函数所调用.定义内部函数格式如下: static 类型标识符 函数名(形参表) 如:static int fun(int x,int y) 使用内部函数,可以使函数的作用域只局限于所在的文件,在不同文件中有同名的内部函数,互不干扰.这样不同的人可以分别编写不同的函数,而不必担心所用函数是否会与其它文件中的函数同

内部函数和外部函数

1 内部函数 如果一个函数只能被本文件中其它函数所调用,它就成为内部函数,在定义内部函数的时候加上static关键字,有点像java中的private. 即 static 类型标识符 函数名(形参)例如: static int fun (int a); 内部函数又称为静态函数,标明该函数不能被其它文件所引用. 2 外部函数 在定义函数时 加上关键字extern 则表示这个函数式外部函数,可以被别的文件调用,这个关键字可以省略掉 内部函数和外部函数,布布扣,bubuko.com