This is the mail archive of the
libffi-discuss@sourceware.org
mailing list for the libffi project.
A closure API example
- From: Conrad Irwin <ctji2 at cam dot ac dot uk>
- To: libffi-discuss at sourceware dot org
- Date: Tue, 12 Jan 2010 19:26:38 +0000
- Subject: A closure API example
Hi,
I'm not sure if this is the best place to send patches (or indeed how
one is supposed to actually use git format-patch), but attached is a
formatted commit to provide an example for the closure API documentation.
Thank you for the phenomenally useful tool.
Conrad
>From 214aaf423778a397499d6f009e42d3e629f17182 Mon Sep 17 00:00:00 2001
From: Conrad Irwin <conrad.irwin@gmail.com>
Date: Tue, 12 Jan 2010 19:10:56 +0000
Subject: [PATCH] Add a closure example to the documentation
---
doc/libffi.info | 94 ++++++++++++++++++++++++++++++++++++++++++++----------
doc/libffi.texi | 60 ++++++++++++++++++++++++++++++++++-
2 files changed, 134 insertions(+), 20 deletions(-)
diff --git a/doc/libffi.info b/doc/libffi.info
index 7a8890e..c5e2925 100644
--- a/doc/libffi.info
+++ b/doc/libffi.info
@@ -1,5 +1,5 @@
-This is ../libffi/doc/libffi.info, produced by makeinfo version 4.13
-from ../libffi/doc/libffi.texi.
+This is doc/libffi.info, produced by makeinfo version 4.13 from
+./doc/libffi.texi.
This manual is for Libffi, a portable foreign-function interface
library.
@@ -89,6 +89,7 @@ File: libffi.info, Node: Using libffi, Next: Missing Features, Prev: Introduc
* Types:: libffi type descriptions.
* Multiple ABIs:: Different passing styles on one platform.
* The Closure API:: Writing a generic function.
+* Closure Example:: A closure example.
File: libffi.info, Node: The Basics, Next: Simple Example, Up: Using libffi
@@ -368,7 +369,7 @@ instance, the x86 platform has both `stdcall' and `fastcall' functions.
necessarily platform-specific.
-File: libffi.info, Node: The Closure API, Prev: Multiple ABIs, Up: Using libffi
+File: libffi.info, Node: The Closure API, Next: Closure Example, Prev: Multiple ABIs, Up: Using libffi
2.5 The Closure API
===================
@@ -386,9 +387,9 @@ determine whether they are supported on the current platform.
require special allocation on platforms that have a non-executable
heap. Memory management for closures is handled by a pair of functions:
- -- Function: void *ffi_closure_alloc (size_t SIZE, void **CODE)
+ -- Function: void *ffi_closure_alloc (size_t SIZE, void **CODELOC)
Allocate a chunk of memory holding SIZE bytes. This returns a
- pointer to the writable address, and sets *CODE to the
+ pointer to the writable address, and sets *CODELOC to the
corresponding executable address.
SIZE should be sufficient to hold a `ffi_closure' object.
@@ -444,6 +445,62 @@ is deprecated, as it cannot handle the need for separate writable and
executable addresses.
+File: libffi.info, Node: Closure Example, Prev: The Closure API, Up: Using libffi
+
+2.6 Closure Example
+===================
+
+A trivial example that creates a new `puts' by binding `fputs' with
+`stdin'.
+
+ #include <stdio.h>
+ #include <ffi.h>
+
+ /* Acts like puts with the file given at time of enclosure. */
+ void puts_binding(ffi_cif *cif, unsigned int *ret, void* args[],
+ FILE *stream)
+ {
+ *ret = fputs(*(char **)args[0], stream);
+ }
+
+ int main()
+ {
+ ffi_cif cif;
+ ffi_type *args[1];
+ ffi_closure *closure;
+
+ int (*bound_puts)(char *);
+ int rc;
+
+ /* Allocate closure and bound_puts */
+ closure = ffi_closure_alloc(sizeof(ffi_closure), &bound_puts);
+
+ if (closure)
+ {
+ /* Initialize the argument info vectors */
+ args[0] = &ffi_type_pointer;
+
+ /* Initialize the cif */
+ if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+ &ffi_type_uint, args) == FFI_OK)
+ {
+ /* Initialize the closure, setting stream to stdout */
+ if (ffi_prep_closure_loc(closure, &cif, puts_binding,
+ stdout, bound_puts) == FFI_OK)
+ {
+ rc = bound_puts("Hello World!");
+ /* rc now holds the result of the call to fputs */
+ }
+ }
+ }
+
+ /* Deallocate both closure, and bound_puts */
+ ffi_closure_free(closure);
+
+ return 0;
+ }
+
+
File: libffi.info, Node: Missing Features, Next: Index, Prev: Using libffi, Up: Top
3 Missing Features
@@ -516,18 +573,19 @@ Index
Tag Table:
-Node: Top700
-Node: Introduction1436
-Node: Using libffi3072
-Node: The Basics3507
-Node: Simple Example6114
-Node: Types7141
-Node: Primitive Types7424
-Node: Structures9244
-Node: Type Example10104
-Node: Multiple ABIs11327
-Node: The Closure API11698
-Node: Missing Features14618
-Node: Index15111
+Node: Top682
+Node: Introduction1418
+Node: Using libffi3054
+Node: The Basics3540
+Node: Simple Example6147
+Node: Types7174
+Node: Primitive Types7457
+Node: Structures9277
+Node: Type Example10137
+Node: Multiple ABIs11360
+Node: The Closure API11731
+Node: Closure Example14681
+Node: Missing Features16238
+Node: Index16731
End Tag Table
diff --git a/doc/libffi.texi b/doc/libffi.texi
index 9a5060d..9e410e9 100644
--- a/doc/libffi.texi
+++ b/doc/libffi.texi
@@ -106,6 +106,7 @@ values passed between the two languages.
* Types:: libffi type descriptions.
* Multiple ABIs:: Different passing styles on one platform.
* The Closure API:: Writing a generic function.
+* Closure Example:: A closure example.
@end menu
@@ -500,12 +501,65 @@ After calling @code{ffi_prep_closure_loc}, you can cast @var{codeloc}
to the appropriate pointer-to-function type.
@end defun
-@c FIXME: example
-
You may see old code referring to @code{ffi_prep_closure}. This
function is deprecated, as it cannot handle the need for separate
writable and executable addresses.
+@node Closure Example
+@section Closure Example
+
+A trivial example that creates a new @code{puts} by binding
+@code{fputs} with @code{stdin}.
+
+@example
+#include <stdio.h>
+#include <ffi.h>
+
+/* Acts like puts with the file given at time of enclosure. */
+void puts_binding(ffi_cif *cif, unsigned int *ret, void* args[],
+ FILE *stream)
+@{
+ *ret = fputs(*(char **)args[0], stream);
+@}
+
+int main()
+@{
+ ffi_cif cif;
+ ffi_type *args[1];
+ ffi_closure *closure;
+
+ int (*bound_puts)(char *);
+ int rc;
+
+ /* Allocate closure and bound_puts */
+ closure = ffi_closure_alloc(sizeof(ffi_closure), &bound_puts);
+
+ if (closure)
+ @{
+ /* Initialize the argument info vectors */
+ args[0] = &ffi_type_pointer;
+
+ /* Initialize the cif */
+ if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+ &ffi_type_uint, args) == FFI_OK)
+ @{
+ /* Initialize the closure, setting stream to stdout */
+ if (ffi_prep_closure_loc(closure, &cif, puts_binding,
+ stdout, bound_puts) == FFI_OK)
+ @{
+ rc = bound_puts("Hello World!");
+ /* rc now holds the result of the call to fputs */
+ @}
+ @}
+ @}
+
+ /* Deallocate both closure, and bound_puts */
+ ffi_closure_free(closure);
+
+ return 0;
+@}
+
+@end example
@node Missing Features
@chapter Missing Features
@@ -525,6 +579,8 @@ There is no support for bit fields in structures.
@item
The closure API is
+@c FIXME: ...
+
@item
The ``raw'' API is undocumented.
@c argument promotion?
--
1.6.5