没有合适的资源?快使用搜索试试~ 我知道了~
温馨提示
Foreign Library Interfaceby Daniel AdlerDecember 13, 2011AbstractWe present an improved Foreign Function Interface (FFI) for R to call arbitary native func- tions without the need for C wrapper code. Further we discuss a dynamic linkage framework for binding standard C libraries to R across platforms using a universal type information format. The package rdyncall comprises the framework and an initial repository of cross-platform bind- ings for standard libraries such as (legacy and modern) Open
资源推荐
资源详情
资源评论
Foreign Library Interface
by Daniel Adler
December 13, 2011
Abstract
We present an improved Foreign Function Interface (FFI) for R to call arbitary native func-
tions without the need for C wrapper code. Further we discuss a dynamic linkage framework for
binding standard C libraries to R across platforms using a universal type information format.
The package rdyncall comprises the framework and an initial repository of cross-platform bind-
ings for standard libraries such as (legacy and modern) OpenGL, the family of SDL libraries
and Expat. The package enables system-level programming using the R language; sample appli-
cations are given in the article. We outline the underlying automation tool-chain that extracts
cross-platform bindings from C headers, making the repository extendable and open for library
developers.
1 Introduction
We present an improved Foreign Function Interface (FFI) for R that significantly reduces the
amount of C wrapper code needed to interface with C. We also introduce a dynamic linkage
that binds the C interface of a pre-compiled library (as a whole) to an interpreted programming
environment (Ousterhout, 1997) such as R - hence th name Foreign Library Interface. Table 1
gives a list of the C libraries currently supported across major R platforms. For each library
supported, abstract interface specifications are declared in a compact platform-neutral text-
based format stored in so-called DynPort files on a local repository.
R (Ross Ihaka and Robert Gentleman, 1996) was choosen as the first language to implement
a proof-of-concept implementation for this approach. This article describes the rdyncall package
which implements a complete toolkit of low-level facilities that can be used as an alternative
FFI to interface with the C programming language. And further, it enables direct and quick
access to the common C libraries from R without compilation.
The project was motivated by the fact that high-quality software solutions implemented in
portable C are often not available in interpreter-based languages such as R. The pool of freely
available C libraries is quite large and represents an invaluable resource for software development.
For example, OpenGL (Board et al., 2005) is the most portable and standard interface to
accelerated graphics hardware for developing real-time graphics software. The combination of
OpenGL with the Simple DirectMedia Layer (SDL) (Lantinga and et al, 2011) core and extension
libraries offers a foundation framework for developing interactive multimedia applications that
can run on a multitude of platforms. Other libraries such as the Expat XML Parser (Clark, 2011)
provide a parser framework for processing very large XML documents. And even the C library
of R contains high-quality statistical functions that are useful in context of other languages as
well.
To make use of these libraries within high-level languages, language bindings to the library
must be written as an extension to the language, a task that requires deep familiarity of the
internals of both the library and the interpreter. Depending on the complexity of the library,
1
lib/dynport description functions constants aggregate types
gl opengl 337 3253 -
glu opengl utility 59 154 -
r r library 238 700 27
sdl audio/video/ui abstraction 203 465 51
sdl_image pixel format loaders 29 - -
sdl_mixer music format loaders and playing 63 12 -
sdl_ttf font format loaders 35 9 -
cuda gpu programming 387 665 84
expat xml parsing framework 65 70 -
glew gl extensions 1465 - -
gl3 opengl 3 (strict) 324 838 1
opencl gpu programming 78 260 10
stdio standard i/o 76 3 -
Table 1: overview of available dynports for portable c libraries
the amount of work needed to wrap the interface can be very large (Table 1 gives the counts of
functions, constants and types that need to be wrapped). Rather than having to write a separate
binding for each library and language combination, we research a dynamic binding approach that
is adaptable to interpreters and works cross-platform without additional compilation of wrapper
layers. Once the binding specification for a library has been specified, that library becomes
automatically accessible to all interpreters that implement such a framework outlined here.
Extension techniques offered by the language interpreter, such as a Foreign Function Interface
(FFI), are the fundamental technology for bridging the dynamic interpreter with statically pre-
compiled code.
In the case of R the built-in FFI function .C provides a fairly basic call gate to C code
with strong limitations; additional wrapper code has to be written in addition to interface with
standard C libraries. rdyncall contributes an improved FFI for R that offers a flexible and
type-safe interface with support for almost all C types without requiring additional C wrappers.
Based on this FFI, the package contains a proof-of-concept implementation of a Foreign
Library Interface that enables direct and dynamic interoperability with foreign C Libraries (in-
cluding shared library code and the Application Programming Interface specified in C headers)
from within the R interpreter. For each C library supported, abstract interface specification
are declared in a compact platform-neutral text-based format stored in a so-called DynPort file
located in a local repository within the package. Table 1 gives a sample list of available bindings
that come with the package.
Users gain access to C libraries from R using the front-end function dynport(portname),
which processes a DynPort file to load the C library
1
, and wrap the C interface as a newly
attached R name space that uses the same symbolic names of the C API. R code that uses C
interfaces via DynPorts might look very familiar to C user code.
This article motivates the topic with a comparison of the built-in and contributed FFI by
means of a simple use case. This leads to a detailed description of the improved FFI. Then
follows an overview of the package and a brief tour through the framework with details on
the handling of foreign C data types and wrapping R functions as callbacks. Two sample
applications are given using OpenGL, SDL and Expat. The article ends with a brief description
1
Pre-compiled libraries need to be installed, OS-specific installation notes are given in the documentation of the
package.
2
of the implementation based on C libraries from the DynCall project (Adler and Philipp, 2011)
and the tool-chain that was used to create the repository of DynPort files.
2 Foreign Function Interfaces
FFIs provide the backbone of a language to interface with foreign code. Depending on the design
of this service, it can largely unburden developers from writing additional wrapper code. In this
section, we compare the built-in FFI with the improved FFI provided by rdyncall using a simple
example that sketches the different work flow paths for making an R binding to a function from
a foreign C library.
2.1 FFI of base R
Suppose that we wish to invoke the C function sqrt of the C Standard Math library. The
function is declared as follows in C:
double sqrt(double x);
R offers a number of functions to call pre-compiled code from within the R interpreter.
While .Call and .External are designed for interoperability with extension code, .C and
.Fortran seem to offer the most low-level interoperability with foreign code. But .C has also
very strict conversion rules and strong limitations regarding argument and return-types: .C
passes R arguments as C pointers and C return types are not supported, so only C void functions,
which are procedures, can be called. Given these limitations, we are not able to invoke the foreign
sqrt function directly and need some intermediate wrapper code written in C that obeys the
rules of the .C interface:
#include <math.h>
void R_C_sqrt(double * ptr_to_x)
{
double x = ptr_to_x[0], ans;
ans = sqrt(x);
ptr_to_x[0] = ans;
}
We assume that the wrapper code is deployed as a shared library in a package named testsqrt
which links to the C math library.
2
. Then we load the testsqrt package and call the C wrapper
function directly via .C.
> library(testsqrt)
> .C("R_C_sqrt", 144, PACKAGE="testsqrt")
[[1]]
[1] 12
To make sqrt available as a public function, an additional R wrapper layer is added, that
does type-safety checks before issuing the .C call.
sqrtViaC <- function(x)
{
x <- as.numeric(x) # type(x) should be C double.
# make sure length > 0:
2
We omit here the details such as registering C functions which is described in detail in the R Manual ’Writing R
Extensions’ (R Development Core Team, 2010).
3
剩余19页未读,继续阅读
资源评论
weixin_38630571
- 粉丝: 8
- 资源: 943
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功