Netscape's introduction of LiveConnect with the 3.0 version of Navigator brings plug-ins, Java applets, and JavaScript programs closer together. LiveConnect provides communication between the three software modules by allowing direct access to methods. As you can see in Figure 14.1, LiveConnect has two interfaces. The first interface, located between a plug-in and a Java applet, allows a plug-in to call Java methods and Java to call the plug-in's methods. The second interface, between Java and JavaScript, allows Java to call JavaScript methods and JavaScript to call Java methods.
Figure 14.1 : LiveConnect interfacing plugins, Java, and JavaScript.
Notice that there is no direct interface between plug-ins and JavaScript. These two must communicate through an intermediate Java applet. This book doesn't attempt to document the Java/JavaScript interface, but instead it concentrates on the plug-in to Java interface.
| Note |
Be sure to download Netscape's latest plug-in SDK to supplement any information in this book. |
To call a Java method from a plug-in, you must use the javah tool that comes in Netscape's plug-in SDK. Running this tool on Java methods generates the appropriate header files for your C++ code to call the Java methods.
For example, if you want to call methods from the java.lang.String class, run javah like this:
javah -jri java.lang.String
This generates the file java_lang_String.h, with accessor macros defined for all methods and fields that are accessible in the Java class. The javah tools also generate java_lang_String.c, which contains all of the stub implementations associated with java_lang_String.h
The type denoting the Java class becomes the C++ class with the same name. Fields can be accessed with inline accessor methods with the following form:
class ClassName :
{
ResultType // getter method
fieldName (JRIEnv* env) { }
void // setter method
fieldName (JRIEnv* env, ResultType value) { }
}
You can get the count field of the String class (created previously with the javah tool) like this:
jint cnt = myString->count (env);
And you can set the same field like this:
myString->count (env, cnt);
Refer to Netscape documentation for C language information.
Java methods can be accessed much like fields. Calling the substring method of the Java String class looks like this in C++:
java_lang_String* sub = str->substring (env, 5, 9);
The javah tool handles overloaded methods in Java by generating symbols that have an index appended to all but the first method. Using an index avoids complex symbol name mangling as is typical in the C++ language. C++ creates new function names based on the original name to differentiate between permutations of overloaded functions. Refer to Netscape documentation for further information on javah symbol names for overloaded methods.
When you are dealing with Java methods from C or C++, you should
use the Java names for primitive types. By using these Java-specific
types, you can keep your C/C++ platform independent. Noteworthy
new type sizes to C/C++ programmers are double-byte characters
and eight-byte longs. These types are defined in jri_md.h,
which is included by jri.h.
The Java primitive types and their C/C++ equivalents are shown
in Table 14.1.
| boolean | jbool | 1 byte |
| byte | jbyte | 1 byte |
| char | jchar | 2 bytes |
| short | jshort | 2 bytes |
| int | jint | 4 bytes |
| long | jlong | 8 bytes |
| float | jfloat | 4 bytes |
| double | jdouble | 8 bytes |
Methods that Java calls within your plug-in are called Plug-in Native Methods. To Java programs, plug-ins appear as instances of the class netscape.plugin.Plugin. This class is a Java reflection of a plug-in. Plug-ins can subclass this class and add new native plug-in methods to it. JavaScript can manipulate a plug-in through this class.
The following sections document the Java class netscape.plugin.Plugin, which allows Java to call methods implemented in a plug-in.
public Plugin()
The constructor initializes this Java class.
public int getPeer()
This method returns the native NPP object-the plug-in instance that is the native part of a Java Plugin object. This field is set by the system, but it can be read from plug-in native methods by the following call:
NPP instance = (NPP)self->getPeer (env);
public void init()
This method is called when the plug-in is initialized. You never need to call this method directly; it is called when the plug-in is created.
public void destroy()
This method is called when the plug-in is destroyed. You never need to call this method directly; it is called when the plug-in is destroyed. At the point where this method is called, the plug-in is still active.
public boolean isActive()
This method determines whether the Java reflection of a plug-in still refers to an active plug-in. Plug-in instances are destroyed whenever the page containing the plug-in is left, thereby causing the plug-in to no longer be active.
public JSObject getWindow()
This method returns the JavaScript window in which the plug-in is embedded.
A plug-in that interfaces with Java might choose to provide the previous Plugin Java class or a subclass of it. This class allows Java to call into the plug-in. You can choose not to provide Java with this class but still call into Java.
For an example of subclassing the netscape.plugin.Plugin Java class, see Chapter 23, "Netscape's LiveConnect Sample," which also shows implementation of native plug-in methods.
The NPP_GetJavaClass plug-in API (documented later in this chapter) associates the Java class with your plug-in.
Garbage collection is a feature of the Java programming language that automatically frees any memory allocations made during the life of the program. Because the C and C++ languages do not have this feature, some memory management issues are involved with C/C++ and Netscape's Java Runtime Interface. You must be especially careful while using global memory in C/C++ to reference Java objects. Check out the latest documentation from Netscape on garbage collection and globals. This information is changing as Netscape continues to enhance LiveConnect.
The following sections give in-depth information on the APIs used in this chapter.
| Compatibility | Windows 3.1/95/NT, Macintosh, UNIX, Navigator 3.0 and above. |
| API Type | Plug-in implemented method. |
| Purpose | Returns the Java class associated with the plug-in. |
| Syntax | jref NPP_GetJavaClass (void) |
| Includes | #include <npapi.h> |
| Description | In order for Java to call a native method in your plug-in, you must associate a Java class with your plug-in by using NPP_GetJavaClass. This API gets the Java environment and then calls the initializer routine for the plug-in implemented Java class. The initializer returns a reference to the Java class, which is also returned by NPP_GetJavaClass. This initializer routine is located in stub code generated by the javah tool. |
| Returns | jref: This is a reference to the Java class representing this plug-in. It is a typedef for a void pointer.
NULL: You return NULL to indicate that a Java class is not associated with your plug-in. |
| See Also | NPN_GetJavaEnv |
| NPN_GetJavaPeer | |
| Example | //
// Get the Java class for this plug-in. // jref NPP_GetJavaClass(void) { // First, get the Java environment JRIEnv* env = NPN_GetJavaEnv(); // Call the native class initializer which returns a // Java class reference. This routine is stub code generated // by the javah tool. return init_AviPlayer(env); } |
| Compatibility | Windows 3.1/95/NT, Macintosh, UNIX, Navigator 3.0 and above. |
| API Type | Navigator implemented method. |
| Purpose | This API returns the Java execution environment needed to make any calls to Java methods from your plug-in using the Java Runtime Interface (JRI). |
| Syntax | JRIEnv* NPN_GetJavaEnv (void); |
| Includes | #include <npapi.h> |
| Description | The NPN_GetJavaEnv API returns a handle to the current Java execution environment, which is supervised by the Java interpreter. The first time you call this, the interpreter might need to initialize itself if the browser has not yet run a Java applet. |
| The Java execution environment encapsulates the current Java thread of execution. Only use the environment handle within the thread that it was requested on. | |
| Returns | JRIEnv*: This is the handle to your current Java execution environment. |
| See Also | NPP_GetJavaClass |
| NPN_GetJavaPeer | |
| Example | //
// Get the Java execution environment // . . . JRIEnv* env = NPN_GetJavaEnv (); . . . |
| Compatibility | Windows 3.1/95/NT, Macintosh, UNIX, Navigator 3.0 and above. |
| API Type | Navigator implemented method. |
| Purpose | This API returns the Java object associated with the plug-in instance. |
| Syntax | jref NPN_GetJavaPeer (NPP instance); |
| Includes | #include <npapi.h> |
| Description | NPN_GetJavaPeer allows your plug-in to access the Java object associated with it by the NPP_GetJavaClass API.
The Java instance is not created until this call is made for the first time. This avoids starting the Java interpreter if you never need the instance. JavaScript implicitly calls this routine if it needs to communicate with a plug-in on the page. |
| Returns | jref: This is a reference to the Java class representing this plug-in. This is a typedef for a void pointer. |
| See Also | NPN_GetJavaEnv |
| Example | //
// Get this plug-in's Java object // . . . AviPlayer* javaAviInst; javaAviInst = (AviPlayer*)NPN_GetJavaPeer (_pluginInstance); . . . |
LiveConnect ties together plug-ins, Java applets, and JavaScript programs. A LiveConnect plug-in interfaces with Java with C/C++ glue generated by Netscape's javah tool. A plug-in can call Java methods, and Java can call plug-in methods. Be sure to use the Java primitive types when dealing with Java methods in your plug-in.
It is important that you supplement this book with current information from Netscape to properly implement a LiveConnect plug-in.
The next chapter is a collection of APIs that didn't really fit into any of the previous chapters. The NPP_SetWindow, NPP_Print, and NPP_HandleEvent APIs are covered.