Arquivos
hhvm/hphp/doc/ffi.java
T
Jordan Delong 363d1bb20f Code move src/ -> hphp/
This change is mostly for FB internal organizational reasons.
Building is not effected beyond the fact that the target now
lands in hphp/hhvm/hhvm rather than src/hhvm/hhvm.
2013-02-11 02:10:41 -08:00

148 linhas
5.7 KiB
Java

<h2>How to Use HipHop Compiled Libraries in Java</h2>
1. Representation of HipHop Data
Each PHP value is wrapped in a Java object. Since PHP does not have a strong
type system, HipHop FFI uses variant as the basic type, which is essentially
the union of all possible types. Whenever a PHP value is exported through FFI
to Java, it is first converted to a variant, and the Java object that
represents the PHP value will store the pointer to that variant, and also
automatically takes care of decreasing the ref count in the PHP world.
The basic classes of the Java FFI are located in <b>hphp/src/ffi/java</b>, and
contained in package "hphp".
Hphp is a utility class containing several static methods for initializing
and finalizing the HipHop environment, etc.
HphpSession is the container of an HipHop session, with an interface similar to
java.lang.Thread. In fact, it is a subclass of Thread, but HipHop session
multi-threading is not supported yet.
HphpVariant is the base class of all the PHP values in the Java world. It has
several subclasses, describing each specific type of PHP values:
- HphpNull
- HphpBoolean
- HphpInt64
- HphpDouble
- HphpString
- HphpArray
- HphpObject
Their meanings are self-explanatory. There is also an HphpArrayIterator
that provides Java-like iteration through a PHP array.
For a particular PHP library that Java FFI is enabled, the HipHop compiler
also generates a Java stub class for each PHP class, as a subclass of
HphpObject. These generated classes are located in a package specified at
compile time with <b>--java-root</b>, and the default is com.facebook.php.
2. Using HipHop Java FFI
The job that you want to submit to Hphp should be enclosed in an object that
extends Runnable. An HphpSession object is created, taking the Runnable object
as the constructor parameter. You can then start the Hphp session by calling
the start() method of the HphpSession object. Note that the start() method in
HphpSession is currently blocking, which means that it will return when the
job finishes.
In the run() method of the Runnable object, one may call functions and methods
provided by library generated by HipHop.
There are two ways of calling into PHP:
(1) Dynamic invocation
This is similar to using call_user_func_array in PHP. PHP functions are called
by their names provided as a String, and the parameters are provided as an
HphpArray. An HphpVariant is returned.
To call a PHP toplevel function f
Hphp.invoke("f", args); // args is of type HphpArray
To call a PHP static method m in class C
Hphp.invoke("C", "m", args);
To call a PHP instance method m
obj.invoke("m", args); // obj is of type HphpObject
(2) Static invocation
Static invocation is similar to normal Java method calls, so that the Java
compiler can checks the signature (but remember, all the parameters and
return types are HphpVariant anyway), and performs better than dynamic
invocation. Static invocation does NOT provide access to PHP built-in
functions. Moreover, non-public methods cannot be called statically.
All the PHP toplevel functions are collected as static methods in class
HphpMain, which is in the package com.facebook.php, or any package specified
with <b>--java-root</b>.
Static and instance methods of a PHP class are called through the corresponding
wrapper class in Java. For example, we have the following PHP class
class A {
public function __construct($a, $b) { ... } // php constructor
public static function m() { ... } // static method
public function n() { ... } // instance method
}
The following sequence of operations in Java will create an object of class A,
and call its methods
A a = new A(1, 2);
A.m(); // static method call
a.n(); // instance method call
Finally, after all the PHP operations are done, remember to call Hphp.finish()
to release resources used by the HipHop session.
3. Object Identification
When a PHP method returns, the result has static type HphpVariant, and
dynamically one of HphpNull, HphpBoolean, HphpInt64, HphpDouble, HphpString,
HphpArray, and HphpObject. However, for performance reason, HipHop Java FFI
does NOT automatically find the exact class type for an HphpObject. Therefore,
an HphpObject, which is not directly created with a static constructor call in
the Java code, cannot be used directly as the receiver for a static invocation.
For example, the following code is NOT going to work:
// calling PHP function f that you know it creates an object of A
HphpObject v = (HphpObject)HphpMain.f();
((A)v).n(); // cast fails, even if v indeed contains a PHP object of A
The correct way is
((A)HphpMain.identify(v)).n(); // this succeeds
Class types are not automatically identified, because it has to use both PHP
reflection and Java reflection, and therefore expensive, and moreover, not
every returned object will be used as the receiver of a static call.
4. Dynamic Libraries
HipHop Java FFI uses JNI as the underlying mechanism, which can only load
dynamic libraries (.so files). Compiling the PHP library with command-line
parameters <b>--format=lib-ffi</b> and <b>--target=cpp</b> will generate a
dynamic library that contains the information of all the required dependencies.
The Java client program needs to load the library with System.loadLibrary(...),
and all these dynamic libraries that it depends on need to be at places that
are searchable by the linker.
5. Session Lifetime
The life of an Hphp session starts when its start() method is called, and
finishes when the method returns. Beyond the session lifetime, all the
Hphp objects (HphpVariant, HphpInt64, HphpArray, etc.) created in the
session are no longer meaningful, because their underlying Hphp objects
have been destroyed.