363d1bb20f
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.
148 linhas
5.7 KiB
Java
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.
|