PHP bindings.

Note that these are not complete on 32 bit architectures.  PHP doesn't
offer any convenient 64 bit type (on 32 bit).  Therefore you should
always use these PHP bindings on 64 bit.
This commit is contained in:
Richard Jones
2010-09-03 12:15:00 +01:00
parent 2d8fd7dacd
commit 2c61e04c45
15 changed files with 733 additions and 2 deletions

18
.gitignore vendored
View File

@@ -181,6 +181,24 @@ perl/Makefile-pl
perl/Makefile-pl.old
perl/Makefile.PL
perl/pm_to_blib
php/extension/Makefile.fragments
php/extension/Makefile.global
php/extension/Makefile.objects
php/extension/acinclude.m4
php/extension/build/
php/extension/config.nice
php/extension/configure.in
php/extension/guestfs_php.c
php/extension/guestfs_php_*.diff
php/extension/guestfs_php_*.exp
php/extension/guestfs_php_*.log
php/extension/guestfs_php_*.out
php/extension/guestfs_php_*.php
php/extension/mkinstalldirs
php/extension/modules/
php/extension/php_guestfs_php.h
php/extension/run-tests.php
php/extension/tmp-php.ini
pod2htm?.tmp
po/*.gmo
po/Makevars.template

View File

@@ -54,6 +54,9 @@ endif
if HAVE_HASKELL
SUBDIRS += haskell
endif
if HAVE_PHP
SUBDIRS += php
endif
# Virt-inspector, tools and guestmount.
if HAVE_INSPECTOR

4
README
View File

@@ -18,7 +18,7 @@ FUSE.
Libguestfs is a library that can be linked with C and C++ management
programs (or management programs written in OCaml, Perl, Python, Ruby,
Java, Haskell or C#). You can also use it from shell scripts or the
Java, PHP, Haskell or C#). You can also use it from shell scripts or the
command line.
Libguestfs was written by Richard W.M. Jones (rjones@redhat.com) and
@@ -96,6 +96,8 @@ in virt-inspector).
- (Optional) po4a for translating manpages and POD files.
- (Optional) PHP, phpize if you want to build the PHP bindings
Running ./configure will check you have all the requirements installed
on your machine.

View File

@@ -772,6 +772,11 @@ dnl po4a for translating man pages and POD files (optional).
AC_CHECK_PROG([PO4A],[po4a],[po4a],[no])
AM_CONDITIONAL([HAVE_PO4A], [test "x$PO4A" != "xno"])
dnl PHP
AC_CHECK_PROG([PHP],[php],[php],[no])
AC_CHECK_PROG([PHPIZE],[phpize],[phpize],[no])
AM_CONDITIONAL([HAVE_PHP], [test "x$PHP" != "xno" -a "x$PHPIZE" != "xno"])
dnl Library versioning.
MAX_PROC_NR=`cat $srcdir/src/MAX_PROC_NR`
AC_SUBST(MAX_PROC_NR)
@@ -808,6 +813,7 @@ AC_CONFIG_FILES([Makefile
fuse/Makefile
po-docs/Makefile
po-docs/ja/Makefile
php/Makefile
ocaml/META perl/Makefile.PL])
AC_OUTPUT
@@ -834,6 +840,8 @@ echo -n "Java bindings ....................... "
if test "x$HAVE_JAVA_TRUE" = "x"; then echo "yes"; else echo "no"; fi
echo -n "Haskell bindings .................... "
if test "x$HAVE_HASKELL_TRUE" = "x"; then echo "yes"; else echo "no"; fi
echo -n "PHP bindings ........................ "
if test "x$HAVE_PHP_TRUE" = "x"; then echo "yes"; else echo "no"; fi
echo -n "virt-inspector ...................... "
if test "x$HAVE_INSPECTOR_TRUE" = "x"; then echo "yes"; else echo "no"; fi
echo -n "virt-* tools ........................ "

58
php/Makefile.am Normal file
View File

@@ -0,0 +1,58 @@
# libguestfs PHP bindings
# Copyright (C) 2010 Red Hat Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
include $(top_srcdir)/subdir-rules.mk
generator_built = \
extension/php_guestfs_php.h \
extension/guestfs_php.c
EXTRA_DIST = \
$(generator_built) \
run-php-tests.sh \
extension/guestfs_php_*.phpt \
extension/config.m4 \
README-PHP \
guestfs_php.ini
if HAVE_PHP
phpdir = $(sysconfdir)/php.d
php_DATA = guestfs_php.ini
# In theory: EXTRA_LIBS="-lguestfs" In fact this doesn't work
# and we need to add the library to EXTRA_LDFLAGS.
all: extension/config.h
$(MAKE) -C extension \
EXTRA_INCLUDES="-I$(abs_srcdir)/../src" \
EXTRA_LDFLAGS="-L$(abs_srcdir)/../src/.libs -lguestfs" \
all
extension/config.h: extension/config.m4 ../config.status
cd extension && phpize
cd extension && ./configure --prefix=$(prefix) --libdir=$(libdir)
test -f "$@" && touch -- $@
TESTS = run-php-tests.sh
clean-local:
$(MAKE) -C extension clean
install-data-hook:
$(MAKE) -C extension INSTALL_ROOT=$(DESTDIR) install
endif

54
php/README-PHP Normal file
View File

@@ -0,0 +1,54 @@
NOTE: The PHP API is not complete on 32 bit architectures. PHP
doesn't offer any convenient 64 bit type (on 32 bit). Any 64 bit
parameters or return values will be truncated to 32 bits on these
platforms. You should always use these PHP bindings on a 64 bit
operating system.
To install the extension manually, copy guestfs_php.so into the
modules directory (eg. /usr/local/lib/php/modules/) and copy
guestfs_php.ini into the config directory (eg. /etc/php.d/).
[Note: On packaged Linux distributions you don't need to do this]
The PHP API follows the C API. Refer to guestfs(3) or
http://libguestfs.org/guestfs.3.html for the details of the C API.
To create a handle, use guestfs_create() like this:
<?php
$g = guestfs_create ();
if ($g == false) {
echo ("Failed to create guestfs_php handle.\n");
exit;
}
?>
Handles are closed implicitly by the PHP dtor.
All of the usual functions from the C API are available. By
convention these return 'false' for errors, so:
<?php
//...
if (guestfs_launch ($g) == false) {
echo ("Error: ".guestfs_last_error ($g)."\n");
exit;
}
?>
or:
<?php
//...
$version = guestfs_version ($g);
if ($version == false) {
echo ("Error: ".guestfs_last_error ($g)."\n");
exit;
}
echo ("libguestfs version = ".
$version["major"].".".$version["minor"].".".$version["release"].
$version["extra"]."\n");
?>
C API structs are mapped to associative arrays. C API lists of
structs are mapped to arrays of associative arrays. Other C API
parameters and return values are mapped to natural PHP types.

24
php/extension/config.m4 Normal file
View File

@@ -0,0 +1,24 @@
# libguestfs PHP bindings
# Copyright (C) 2010 Red Hat Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
PHP_ARG_ENABLE(guestfs_php, enable libguestfs PHP bindings,
[ --enable-guestfs-php Enable libguestfs support])
if test "$PHP_GUESTFS_PHP" = "yes"; then
AC_DEFINE(HAVE_GUESTFS_PHP, 1, [Whether you have libguestfs PHP bindings])
PHP_NEW_EXTENSION(guestfs_php, guestfs_php.c, $ext_shared)
fi

View File

@@ -0,0 +1,17 @@
--TEST--
Load the module and create a handle.
--FILE--
<?php
// See comment in php/run-php-tests.sh.
//putenv ('LIBGUESTFS_DEBUG=1');
$g = guestfs_create ();
if ($g == false) {
echo ("Failed to create guestfs_php handle.\n");
exit;
}
echo ("Created guestfs_php handle.\n");
?>
--EXPECT--
Created guestfs_php handle.

View File

@@ -0,0 +1,36 @@
--TEST--
Launch the appliance.
--FILE--
<?php
// See comment in php/run-php-tests.sh.
//putenv ('LIBGUESTFS_DEBUG=1');
$g = guestfs_create ();
if ($g == false) {
echo ("Failed to create guestfs_php handle.\n");
exit;
}
if (guestfs_add_drive ($g, "/dev/null") == false) {
echo ("Error: ".guestfs_last_error ($g)."\n");
exit;
}
if (guestfs_launch ($g) == false) {
echo ("Error: ".guestfs_last_error ($g)."\n");
exit;
}
$version = guestfs_version ($g);
if ($version == false) {
echo ("Error: ".guestfs_last_error ($g)."\n");
exit;
}
if (!is_int ($version["major"]) ||
!is_int ($version["minor"]) ||
!is_int ($version["release"]) ||
!is_string ($version["extra"])) {
echo ("Error: incorrect return type from guestfs_version\n");
}
echo ("OK\n");
?>
--EXPECT--
OK

View File

@@ -0,0 +1,39 @@
--TEST--
Create a disk containing LV and filesystem.
--FILE--
<?php
// See comment in php/run-php-tests.sh.
//putenv ('LIBGUESTFS_DEBUG=1');
$g = guestfs_create ();
if ($g == false) {
die ("Failed to create guestfs_php handle.\n");
}
$tmp = dirname(__FILE__)."/test.img";
$size = 100 * 1024 * 1024;
if (! $fp = fopen ($tmp, 'r+')) {
die ("Error: cannot create file '".$tmp."'\n");
}
ftruncate ($fp, $size);
fclose ($fp);
if (! guestfs_add_drive ($g, "test.img") ||
! guestfs_launch ($g) ||
! guestfs_part_disk ($g, "/dev/sda", "mbr") ||
! guestfs_pvcreate ($g, "/dev/sda") ||
! guestfs_vgcreate ($g, "VG", array ("/dev/sda")) ||
! guestfs_lvcreate ($g, "LV", "VG", 64) ||
! guestfs_mkfs ($g, "ext2", "/dev/VG/LV")) {
die ("Error: ".guestfs_last_error ($g)."\n");
}
echo ("OK\n");
?>
--CLEAN--
<?php
$tmp = dirname(__FILE__)."/test.img";
unlink ($tmp);
?>
--EXPECT--
OK

2
php/guestfs_php.ini Normal file
View File

@@ -0,0 +1,2 @@
; Enable guestfs_php extension module
extension=guestfs_php.so

35
php/run-php-tests.sh Executable file
View File

@@ -0,0 +1,35 @@
#!/bin/sh -
# Copyright (C) 2010 Red Hat Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
set -e
cd extension
TESTS=$(echo guestfs_php_*.phpt)
echo TESTS: $TESTS
# The PHP test script cleans the environment, so LIBGUESTFS_DEBUG=1
# won't get passed down to the script. Furthermore, setting
# LIBGUESTFS_DEBUG=1 isn't very useful anyway because the PHP test
# script mixes stdout and stderr together and compares this to the
# expected output, so you'd just get failures for every test. So
# there is no good way to debug libguestfs failures in PHP tests, but
# if an individual test fails locally then you can edit the
# guestfs_php_*.phpt and uncomment the putenv statement, then look at
# the output.
unset LIBGUESTFS_DEBUG
make test TESTS="$TESTS"

View File

@@ -98,6 +98,7 @@ perl/Guestfs.c
perl/bindtests.pl
perl/lib/Sys/Guestfs.pm
perl/lib/Sys/Guestfs/Lib.pm
php/extension/guestfs_php.c
python/guestfs-py.c
regressions/rhbz501893.c
regressions/test-lvm-mapping.pl

View File

@@ -11978,6 +11978,431 @@ namespace Guestfs
}
"
and generate_php_h () =
generate_header CStyle LGPLv2plus;
pr "\
#ifndef PHP_GUESTFS_PHP_H
#define PHP_GUESTFS_PHP_H 1
#ifdef ZTS
#include \"TSRM.h\"
#endif
#define PHP_GUESTFS_PHP_EXTNAME \"guestfs_php\"
#define PHP_GUESTFS_PHP_VERSION \"1.0\"
PHP_MINIT_FUNCTION (guestfs_php);
#define PHP_GUESTFS_HANDLE_RES_NAME \"guestfs_h\"
PHP_FUNCTION (guestfs_create);
PHP_FUNCTION (guestfs_last_error);
";
List.iter (
fun (shortname, style, _, _, _, _, _) ->
pr "PHP_FUNCTION (guestfs_%s);\n" shortname
) all_functions_sorted;
pr "\
extern zend_module_entry guestfs_php_module_entry;
#define phpext_guestfs_php_ptr &guestfs_php_module_entry
#endif /* PHP_GUESTFS_PHP_H */
"
and generate_php_c () =
generate_header CStyle LGPLv2plus;
pr "\
/* NOTE: Be very careful with all macros in PHP header files. The
* morons who wrote them aren't good at making them safe for inclusion
* in arbitrary places in C code, eg. not using 'do ... while(0)'
* or parenthesizing any of the arguments.
*/
/* NOTE (2): Some parts of the API can't be used on 32 bit platforms.
* Any 64 bit numbers will be truncated. There's no easy way around
* this in PHP.
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <php.h>
#include <php_guestfs_php.h>
#include \"guestfs.h\"
static int res_guestfs_h;
static void
guestfs_php_handle_dtor (zend_rsrc_list_entry *rsrc TSRMLS_DC)
{
guestfs_h *g = (guestfs_h *) rsrc->ptr;
if (g != NULL)
guestfs_close (g);
}
PHP_MINIT_FUNCTION (guestfs_php)
{
res_guestfs_h =
zend_register_list_destructors_ex (guestfs_php_handle_dtor,
NULL, PHP_GUESTFS_HANDLE_RES_NAME, module_number);
}
static function_entry guestfs_php_functions[] = {
PHP_FE (guestfs_create, NULL)
PHP_FE (guestfs_last_error, NULL)
";
List.iter (
fun (shortname, style, _, _, _, _, _) ->
pr " PHP_FE (guestfs_%s, NULL)\n" shortname
) all_functions_sorted;
pr " { NULL, NULL, NULL }
};
zend_module_entry guestfs_php_module_entry = {
#if ZEND_MODULE_API_NO >= 20010901
STANDARD_MODULE_HEADER,
#endif
PHP_GUESTFS_PHP_EXTNAME,
guestfs_php_functions,
PHP_MINIT (guestfs_php),
NULL,
NULL,
NULL,
NULL,
#if ZEND_MODULE_API_NO >= 20010901
PHP_GUESTFS_PHP_VERSION,
#endif
STANDARD_MODULE_PROPERTIES
};
#ifdef COMPILE_DL_GUESTFS_PHP
ZEND_GET_MODULE (guestfs_php)
#endif
PHP_FUNCTION (guestfs_create)
{
guestfs_h *g = guestfs_create ();
if (g == NULL) {
RETURN_FALSE;
}
guestfs_set_error_handler (g, NULL, NULL);
ZEND_REGISTER_RESOURCE (return_value, g, res_guestfs_h);
}
PHP_FUNCTION (guestfs_last_error)
{
zval *z_g;
guestfs_h *g;
if (zend_parse_parameters (ZEND_NUM_ARGS() TSRMLS_CC, \"r\",
&z_g) == FAILURE) {
RETURN_FALSE;
}
ZEND_FETCH_RESOURCE (g, guestfs_h *, &z_g, -1, PHP_GUESTFS_HANDLE_RES_NAME,
res_guestfs_h);
if (g == NULL) {
RETURN_FALSE;
}
const char *err = guestfs_last_error (g);
if (err) {
RETURN_STRING (err, 1);
} else {
RETURN_NULL ();
}
}
";
(* Now generate the PHP bindings for each action. *)
List.iter (
fun (shortname, style, _, _, _, _, _) ->
pr "PHP_FUNCTION (guestfs_%s)\n" shortname;
pr "{\n";
pr " zval *z_g;\n";
pr " guestfs_h *g;\n";
List.iter (
function
| String n | Device n | Pathname n | Dev_or_Path n
| FileIn n | FileOut n | Key n
| OptString n
| BufferIn n ->
pr " char *%s;\n" n;
pr " int %s_size;\n" n
| StringList n
| DeviceList n ->
pr " zval *z_%s;\n" n;
pr " char **%s;\n" n;
| Bool n ->
pr " zend_bool %s;\n" n
| Int n | Int64 n ->
pr " long %s;\n" n
) (snd style);
pr "\n";
(* Parse the parameters. *)
let param_string = String.concat "" (
List.map (
function
| String n | Device n | Pathname n | Dev_or_Path n
| FileIn n | FileOut n | BufferIn n | Key n -> "s"
| OptString n -> "s!"
| StringList n | DeviceList n -> "a"
| Bool n -> "b"
| Int n | Int64 n -> "l"
) (snd style)
) in
pr " if (zend_parse_parameters (ZEND_NUM_ARGS() TSRMLS_CC, \"r%s\",\n"
param_string;
pr " &z_g";
List.iter (
function
| String n | Device n | Pathname n | Dev_or_Path n
| FileIn n | FileOut n | BufferIn n | Key n
| OptString n ->
pr ", &%s, &%s_size" n n
| StringList n | DeviceList n ->
pr ", &z_%s" n
| Bool n ->
pr ", &%s" n
| Int n | Int64 n ->
pr ", &%s" n
) (snd style);
pr ") == FAILURE) {\n";
pr " RETURN_FALSE;\n";
pr " }\n";
pr "\n";
pr " ZEND_FETCH_RESOURCE (g, guestfs_h *, &z_g, -1, PHP_GUESTFS_HANDLE_RES_NAME,\n";
pr " res_guestfs_h);\n";
pr " if (g == NULL) {\n";
pr " RETURN_FALSE;\n";
pr " }\n";
pr "\n";
List.iter (
function
| String n | Device n | Pathname n | Dev_or_Path n
| FileIn n | FileOut n | Key n
| OptString n ->
(* Just need to check the string doesn't contain any ASCII
* NUL characters, which won't be supported by the C API.
*)
pr " if (strlen (%s) != %s_size) {\n" n n;
pr " fprintf (stderr, \"libguestfs: %s: parameter '%s' contains embedded ASCII NUL.\\n\");\n" shortname n;
pr " RETURN_FALSE;\n";
pr " }\n";
pr "\n"
| BufferIn n -> ()
| StringList n
| DeviceList n ->
(* Convert array to list of strings.
* http://marc.info/?l=pecl-dev&m=112205192100631&w=2
*)
pr " {\n";
pr " HashTable *a;\n";
pr " int n;\n";
pr " HashPosition p;\n";
pr " zval **d;\n";
pr " size_t c = 0;\n";
pr "\n";
pr " a = Z_ARRVAL_P (z_%s);\n" n;
pr " n = zend_hash_num_elements (a);\n";
pr " %s = safe_emalloc (n + 1, sizeof (char *), 0);\n" n;
pr " for (zend_hash_internal_pointer_reset_ex (a, &p);\n";
pr " zend_hash_get_current_data_ex (a, (void **) &d, &p) == SUCCESS;\n";
pr " zend_hash_move_forward_ex (a, &p)) {\n";
pr " zval t = **d;\n";
pr " zval_copy_ctor (&t);\n";
pr " convert_to_string (&t);\n";
pr " %s[c] = Z_STRVAL (t);\n" n;
pr " c++;\n";
pr " }\n";
pr " %s[c] = NULL;\n" n;
pr " }\n";
pr "\n"
| Bool n | Int n | Int64 n -> ()
) (snd style);
(* Return value. *)
let error_code =
match fst style with
| RErr -> pr " int r;\n"; "-1"
| RBool _
| RInt _ -> pr " int r;\n"; "-1"
| RInt64 _ -> pr " int64_t r;\n"; "-1"
| RConstString _ -> pr " const char *r;\n"; "NULL"
| RConstOptString _ -> pr " const char *r;\n"; "NULL"
| RString _ ->
pr " char *r;\n"; "NULL"
| RStringList _ ->
pr " char **r;\n"; "NULL"
| RStruct (_, typ) ->
pr " struct guestfs_%s *r;\n" typ; "NULL"
| RStructList (_, typ) ->
pr " struct guestfs_%s_list *r;\n" typ; "NULL"
| RHashtable _ ->
pr " char **r;\n"; "NULL"
| RBufferOut _ ->
pr " char *r;\n";
pr " size_t size;\n";
"NULL" in
(* Call the function. *)
pr " r = guestfs_%s " shortname;
generate_c_call_args ~handle:"g" style;
pr ";\n";
pr "\n";
(* Free up parameters. *)
List.iter (
function
| String n | Device n | Pathname n | Dev_or_Path n
| FileIn n | FileOut n | Key n
| OptString n -> ()
| BufferIn n -> ()
| StringList n
| DeviceList n ->
pr " {\n";
pr " size_t c = 0;\n";
pr "\n";
pr " for (c = 0; %s[c] != NULL; ++c)\n" n;
pr " efree (%s[c]);\n" n;
pr " efree (%s);\n" n;
pr " }\n";
pr "\n"
| Bool n | Int n | Int64 n -> ()
) (snd style);
(* Check for errors. *)
pr " if (r == %s) {\n" error_code;
pr " RETURN_FALSE;\n";
pr " }\n";
pr "\n";
(* Convert the return value. *)
(match fst style with
| RErr ->
pr " RETURN_TRUE;\n"
| RBool _ ->
pr " RETURN_BOOL (r);\n"
| RInt _ ->
pr " RETURN_LONG (r);\n"
| RInt64 _ ->
pr " RETURN_LONG (r);\n"
| RConstString _ ->
pr " RETURN_STRING (r, 1);\n"
| RConstOptString _ ->
pr " if (r) { RETURN_STRING (r, 1); }\n";
pr " else { RETURN_NULL (); }\n"
| RString _ ->
pr " char *r_copy = estrdup (r);\n";
pr " free (r);\n";
pr " RETURN_STRING (r_copy, 0);\n"
| RBufferOut _ ->
pr " char *r_copy = estrndup (r, size);\n";
pr " free (r);\n";
pr " RETURN_STRING (r_copy, 0);\n"
| RStringList _ ->
pr " size_t c = 0;\n";
pr " array_init (return_value);\n";
pr " for (c = 0; r[c] != NULL; ++c) {\n";
pr " add_next_index_string (return_value, r[c], 1);\n";
pr " free (r[c]);\n";
pr " }\n";
pr " free (r);\n";
| RHashtable _ ->
pr " size_t c = 0;\n";
pr " array_init (return_value);\n";
pr " for (c = 0; r[c] != NULL; c += 2) {\n";
pr " add_assoc_string (return_value, r[c], r[c+1], 1);\n";
pr " free (r[c]);\n";
pr " free (r[c+1]);\n";
pr " }\n";
pr " free (r);\n";
| RStruct (_, typ) ->
let cols = cols_of_struct typ in
generate_php_struct_code typ cols
| RStructList (_, typ) ->
let cols = cols_of_struct typ in
generate_php_struct_list_code typ cols
);
pr "}\n";
pr "\n"
) all_functions_sorted
and generate_php_struct_code typ cols =
pr " array_init (return_value);\n";
List.iter (
function
| name, FString ->
pr " add_assoc_string (return_value, \"%s\", r->%s, 1);\n" name name
| name, FBuffer ->
pr " add_assoc_stringl (return_value, \"%s\", r->%s, r->%s_len, 1);\n"
name name name
| name, FUUID ->
pr " add_assoc_stringl (return_value, \"%s\", r->%s, 32, 1);\n"
name name
| name, (FBytes|FUInt64|FInt64|FInt32|FUInt32) ->
pr " add_assoc_long (return_value, \"%s\", r->%s);\n"
name name
| name, FChar ->
pr " add_assoc_stringl (return_value, \"%s\", &r->%s, 1, 1);\n"
name name
| name, FOptPercent ->
pr " add_assoc_double (return_value, \"%s\", r->%s);\n"
name name
) cols;
pr " guestfs_free_%s (r);\n" typ
and generate_php_struct_list_code typ cols =
pr " array_init (return_value);\n";
pr " size_t c = 0;\n";
pr " for (c = 0; c < r->len; ++c) {\n";
pr " zval *z_elem;\n";
pr " ALLOC_INIT_ZVAL (z_elem);\n";
pr " array_init (z_elem);\n";
List.iter (
function
| name, FString ->
pr " add_assoc_string (z_elem, \"%s\", r->val[c].%s, 1);\n"
name name
| name, FBuffer ->
pr " add_assoc_stringl (z_elem, \"%s\", r->val[c].%s, r->val[c].%s_len, 1);\n"
name name name
| name, FUUID ->
pr " add_assoc_stringl (z_elem, \"%s\", r->val[c].%s, 32, 1);\n"
name name
| name, (FBytes|FUInt64|FInt64|FInt32|FUInt32) ->
pr " add_assoc_long (z_elem, \"%s\", r->val[c].%s);\n"
name name
| name, FChar ->
pr " add_assoc_stringl (z_elem, \"%s\", &r->val[c].%s, 1, 1);\n"
name name
| name, FOptPercent ->
pr " add_assoc_double (z_elem, \"%s\", r->val[c].%s);\n"
name name
) cols;
pr " add_next_index_zval (return_value, z_elem);\n";
pr " }\n";
pr " guestfs_free_%s_list (r);\n" typ
and generate_bindtests () =
generate_header CStyle LGPLv2plus;
@@ -12517,6 +12942,8 @@ Run it from the top source directory using the command
output_to "haskell/Guestfs.hs" generate_haskell_hs;
output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
output_to "csharp/Libguestfs.cs" generate_csharp;
output_to "php/extension/php_guestfs_php.h" generate_php_h;
output_to "php/extension/guestfs_php.c" generate_php_c;
(* Always generate this file last, and unconditionally. It's used
* by the Makefile to know when we must re-run the generator.

View File

@@ -43,7 +43,7 @@ FUSE.
Libguestfs is a library that can be linked with C and C++ management
programs (or management programs written in OCaml, Perl, Python, Ruby,
Java, Haskell or C#). You can also use it from shell scripts or the
Java, PHP, Haskell or C#). You can also use it from shell scripts or the
command line.
You don't need to be root to use libguestfs, although obviously you do
@@ -626,6 +626,13 @@ For documentation see the file C<guestfs.mli>.
For documentation see L<Sys::Guestfs(3)>.
=item B<PHP>
For documentation see C<README-PHP> supplied with libguestfs
sources or in the php-libguestfs package for your distribution.
The PHP binding only works correctly on 64 bit machines.
=item B<Python>
For documentation do: