Libffi介绍
高级语言的编译器根据一定的规则生成代码,这些规则对于不同编译器的工作是必须的。其中一个规则叫做“调用规则”(Calling Convention),它包含了编译器关于在函数入口处函数参数位置、函数返回值位置的一系列假设。它有时也被称作“ABI”(Application Binary Interface)。
一些程序在编译时可能不知道传给函数的参数是什么,例如,解释器在运行时才被告知调用给定函数的参数类型和数量。Libffi可以在这些函数中看做是连接要解释的函数和编译后的代码之间的桥梁。
“Libffi”库为多种调用规则提供了可移植的高级语言编程接口,这使得程序员在运行时可以调用任何由调用接口指定的函数。
FFI(Foreign Function Interface)允许以一种语言编写的代码调用另一种语言的代码,而Libffi库提供了最底层的、与架构相关的、完整的FFI,因此在它的上层必须有函数来管理两种语言之间参数的格式转换。
1.2 如何使用FFI
1.2.1 FFI使用流程
Libffi假设你有要调用的函数的指针、要传递的参数的类型和数量以及该函数返回值的类型。
第一步你必须创建与你要调用的函数特征相匹配的“ffi_cif”对象,这是单独的一步因为多次调用一个“ffi_cif”对象很常见(其中的“cif”指的是Call Interface)。要创建“ffi_cif”对象必须调用函数“ffi_prep_cif”。
声明位置:Android2.1/external/libffi/include/ffi_real.h Line 348
ffi_status ffi_prep_cif(ffi_cif *cif,
ffi_abi abi,
unsigned int nargs,
ffi_type *rtype,
ffi_type **atypes);
实现位置:Android/external/Libffi/src/prep_cif.c Line 88
ffi_prep_cif(ffi_cif *cif, ffi_abi abi, unsigned int nargs,ffi_type *rtype, ffi_type **atypes)
参数解释:
abi:要使用的ABI,通常使用FFI_DEFAULT_ABI就可以了;
nargs:函数接受的参数的数量;
rtype:指向FFI_TYPE结构体的指针,描述函数的返回类型;
argtypes:FFI_TYPE结构体的向量,其中必须包含nargs元素。
ffi_prep_cif返回“ffi_status”类型变量,如果初始化正确则返回“FFI_OK”,如果一个“ffi_type”对象错误则返回“FFI_BAD_TYPEDEF”,如果ABI参数错误则返回“FFI_BAD_ABI”。
第二步你必须调用“ffi_call”函数来调用初始化的“ffi_cif”对象。
声明位置:Android2.1/external/libffi/include/ffi_real.h Line 354
void ffi_call(ffi_cif *cif,
void (*fn)(void),
void *rvalue,
void **avalue);
实现位置:由Android2.1/external/libffi/src下各架构中ffi.c实现
参数解释:
cif:由“ffi_prep_cif”指定的cif;
fn:根据cif的不同调用函数fn;
rvalue:一块内存的指针,存放函数调用返回的结果。它必须足够大并且合理分配,由调用者负责确保这一点;
avalue:一个“void *”指针用来指向保存调用函数参数的存放地址。
2、Android2.1 Libffi的实现
2.1 FFI的实现
在Android2.1中Libffi整体作为外部文件放在/external/libffi实现,其目录架构如下:
目录:/Android2.1/external/libffi/
主要结构分析:
-doc libffi的文档管理。
--libffi.info libffi的介绍;
--libffi.texi 定义了libffi需要的部分API,可以看成是定义了部分全局变量;
--stamp-vti (?)版本管理的记录;
--version.texi 同上;
-include 头文件。
--ffi.h.in 定义了libffi需要的部分API,可以看成是定义了部分全局变量;
--ffi_common.h 定义了编译libffi必须的内部变量和宏;
--ffi_real.h 内容几乎同ffi.h.in,仅将与架构相关的几行重新另写为ffitarget.h放
在/Android2.1/external/libffi/src/各个架构下面;
--Makefile.am Makefile文件,指定头文件的编译过程,由上层make调用;
--Makefile.in Makefile.am生成;
-linux-arm arm架构的头文件。
--ffi.h arm架构下ffi所需的头文件;
--fficonfig.h arm架构下ffi配置文件,定义了一些宏;
-linux-x86 x86架构的头文件。
--ffi.h x86架构下ffi所需的头文件(和arm下几乎一样);
--fficonfig.h x86架构下ffi配置文件,定义了一些宏(和arm下几乎一样,多定
义了一些宏);
-man (?)重要函数几乎的机器语言解释。
--ffi.3 初始化ffi的机器级解释;
--ffi_call.3 ffi_call函数的机器级解释;
--ffi_prep_cif.3 ffi_prep_cif函数的机器级解释;
--Makefile.am Makefile文件,指定编译方法,由上层make调用;
--Makefile.in 由Makefile.am生成;
-src 不同架构下ffi的实现,包括alpha、arm、cris、frv、IA64、M32R、M68K、MIPS、
PA、powerpc、s390、SH、SH64、sparc和X86架构,每个架构有单独的文件夹,下面仅分析arm、x86架构文件夹。
--arm
---ffi.c 实现ffi的基本函数的实现;
--ffitarget.h 头文件,在/…/linux-arm/ffi.h中调用;
--sysv.S 定义了函数ffi_closure_SYSV、ffi_call_SYSV等,实际完成ffi_call等函
数功能;
--x86
--ffi.c 实现ffi的基本函数的实现;
--ffitarget.h 头文件,在/…/linux-arm/ffi.h中调用;
--sysv.S 定义了函数ffi_closure_SYSV、ffi_call_SYSV等,实际完成ffi_call等函
数功能;
--其它文件为*.S,为Darwin、UNIX64、WIN32、FREEBSD操作系统下ffi的汇编实现。
--prep_cif.c 准备好函数的cif;
--closures.c 定义了Closure API相关的方法;
--dlmalloc.c 与内存分配、malloc相关的东西;
--types.c 定义了ffi需要的TYPE;
--raw_api.c 定义了Raw API相关的方法;
--java_raw_api.c 定义了仿Java的Raw API相关的方法,和raw API差不多;
--debug.c debug ffi时需要的方法;
-testsuite (?)测试用的方法,暂时未看。
-Android.mk Makefile文件,只定义了arm和x86架构的编译流程,生成libffi库文件。
-ChangeLog.* 修改日志,可以便于理解。
-compile 编译器需要的,解释-c、-o命令。
-configure.ac 用来生成configure执行文件。
-Makefile.am 整个libffi的编译规则,生成Makefile.in。
其中raw API和closure API是用来传参、封装方法的接口:raw API是用来绕过由架构封装或者未封装的参数;closure API将解释过的函数封装进C指针,从而可以作为C函数来看,这也可以用在将用户参数和函数指针封装到一个函数指针里面(这正是ffi要做的,因此closure API一定要实现)。
2.2 Android Libffi调用
在/Android2.1/dalvik/vm/Dvm.mk中有以下语句:
ifeq ($(MTERP_ARCH_KNOWN),false)
# unknown architecture, try to use FFI
LOCAL_C_INCLUDES += external/libffi/$(dvm_os)-$(dvm_arch)
LOCAL_SHARED_LIBRARIES += libffi
LOCAL_SRC_FILES += \
arch/generic/Call.c \
arch/generic/Hints.c \
mterp/out/InterpC-allstubs.c
在Android2.1里,对于未知架构android将调用libffi来处理不同语言的函数调用问题,调用的源文件位于/android2.1/dalvik/vm/arch/generic/Calls.c和Hints.c;而对于确定的架构(例如ARM、X86、MIPS等)则采用他们架构相关的方法来处理该问题。
分享到:
相关推荐
"libffi-3.4.5.tar.gz" 是一个软件库的压缩包文件,其中包含了libffi版本3.4.5的所有源代码和其他相关文件。libffi是一个通用、低级的函数调用接口(Foreign Function Interface),它允许程序动态地调用其他编程...
libffi-3.0.5-3.2.el6.x86_64.rpm和libffi-3.0.5-3.2.el6.i686.rpm是libffi的运行时库,而libffi-devel-3.0.5-3.2.el6.i686.rpm和libffi-devel-3.0.5-3.2.el6.x86_64.rpm则是对应的开发包,包含头文件和开发所需的...
标题"libffi-3.2.1.tar.gz"表明这是一个软件库的压缩文件,名为"libffi",版本号为3.2.1,使用的压缩格式是tar.gz。在Linux和类Unix系统中,这种格式常见于源代码分发,因为它可以将多个文件和目录打包并压缩成一个...
**标题:“libffi-3.0.13.tar.gz”** **描述:**该压缩包“libffi-3.0.13.tar.gz”包含了libffi库的一个版本,即3.0.13,它是glib和GTK在Linux环境下运行所依赖的一个关键组件。libffi是一个通用的、开源的函数调用...
标题中的"libffi-3.2.tar.gz"是一个开源库的源码压缩包,libffi是“Foreign Function Interface”的缩写,它是一个跨平台的库,用于动态调用其他编程语言的函数。在Python中,libffi常用于实现C语言级别的函数调用,...
The libffi library is useful to anyone trying to build a bridge between interpreted and natively compiled code.
标题"cpp-libffi一个便携式外部功能接口库"指的是一个用于C++的库,它利用了libffi这个开源项目,旨在提供一个跨平台的、用于调用外部函数的接口。libffi是一个通用的、低级别的接口,允许程序动态地调用任何已知...
libffi-devel-3.0.5-3.2.el6.x86_64.rpm
安装libffi的包。欢迎大家积极下载。其它地方不好找这个资源。
libffi-devel-3.0.9-1.el5.rf.x86-64.rpm
标题"libffi-3.0.10"指的是libffi库的一个具体版本,这里是3.0.10版。libffi是一个开源的、跨平台的库,它提供了一种灵活的机制来调用函数,无论其接口如何定义。这个标题意味着我们将讨论的是关于libffi库的这一...
libffi-devel-3.0.5-4.el6.x86_64.rpm
libffi-3.0.5-3.2.el6.x86-64.rpm
而 “Libffi” 库只提供了最底层的、与架构相关的、完整的”FFI”,因此在它之上必须有一层来负责管理两种语言之间参数的格式转换。 高级语言编译器产生代码时都会依据一系列的规则,这些规则十分必要,特别是对...
libffi, 一个便携式外部函数接口 状态 libffi-3.3-rc0 于,发布。 查看libffi网页以获取更新: URL:http://sourceware.org/libffi/.什么是 libffi?高级语言的编译器生成遵循某些约定的代码。 这些约定是必
《关于在CentOS 6.9上安装Python3及其依赖:libffi-devel详解》 在进行Python3的安装过程中,我们经常会遇到各种依赖问题。其中一个关键的依赖是`libffi-devel`,它对于构建和运行Python3至关重要。本文将详细阐述`...
vs2015成功编译glib2.5,包括libffi,pcre,glib,libintl,libiconv等