This release of Jaco is very preliminary, as is this documentation. Items in the documentation in red are planned but not yet implemented.
The goal of Jaco is to make it easy to access C++ objects from Java. All Java virtual machines include a mechanism for calling routines written in other languages, called the Java Native Interface (JNI). The JNI is fine for calling routines written in C (or event Fortran) from Java, but it does not by itself provide a convenient mechanism for making C++ objects accessible to the Java programmer as Java objects. Accessing a C++ object from Java using JNI typically involves hand coding a combination of C and Java code for each method in the C++ object, a tedious and error-prone task.
Jaco addresses this problem by automating the generation of this glue code, and in addition provides some extra functionality to aid in managing objects in a cross-language environment. The basic OO functionality of Java and C++ is very similar, so there is a fairly natural mapping between C++ objects and Java objects. C++ does support a number of features which are not supported by Java and currently these features are not supported by Jaco. Limitations currently imposed by Jaco include:
Jaco does support
Jaco maps each C++ object to a Java object, called a proxy. Each Java proxy will implement an interface of the same name as the C++ class, and with the same public methods as the corresponding C++ class. Jaco supports multiple inheritance, so for each superclass of the C++ class the Java object will implement a super-interface of the C++ class. Each Java proxy object will also implement a CPPProxy interface, which has a few utility methods in it applicable to all proxy classes. This is illustrated below.
Jaco maintains a table which maps C++ classes to their Java Proxy (and vice-versa). This enables Jaco to guarantee that if two references to the same C++ object exist in the Java program, they will both refer to the same Java proxy object. Java proxy objects will be automatically garbage when they are no longer in use, and the entry in the Jaco map will be automatically cleaned up too. Various objection exist for handling the C++ objects when their Java proxy is garbage collected.
Jaco is designed to be used in two different ways:
The details of how Jaco is used is slightly different in these two cases, and is described separately below.
To be written.
C++ objects can be created from a Java program, but the mechanism is not as simple as using the normal Java new operator. Since each C++ class is represented in the Java program by a Java interface, a compile time error will occur if an attempt is made to use the new operator. (Java interfaces can not be created with the new operator).
Instead the create method in the corresponding Proxy class must be called (the proxy class has the same name as the C++ class, but with the postfix Proxy). One create method will exist for each (overloaded) public constructor in the C++ class.
Track t = TrackProxy.create();
C++ objects can be deleted from Java by calling the delete method in the CPPProxy interface which all Java proxy objects implement. Once a C++ object has been explicitly deleted any attempt to call a method of the proxy object will result in a NoSuchObject exception.
Track t = TrackProxy.create(); t.delete();
Static methods in C++ classes can be called by invoking the static method with the same name on the Java proxy class, e.g.:
TrackProxy.setPrimaryVertex(v);
C++ objects allocated on the heap, must be explicitly deleted by the user when they are no longer needed. Java objects on the other hand are automatically deleted by the system when they are no longer in use (a process called garbage collection). Jaco allows C++ objects to be explicitly created and deleted using the mechanisms discussed above. In addition a Java proxy can be set to automatically delete its corresponding C++ object when the Java object is no longer in use, using the setDeleteCPPObjectWhenProxyFinalized() method in the CPPProxy interface which all Java proxy objects implement. This must be used with care since there is no check whether other C++ objects have references to the C++ object being deleted.
Track t = TrackProxy.create(); t.setDeleteCPPObjectWhenProxyFinalized();
In the case where a C++ object is deleted explicitly from Java, any further attempt to invoke methods of its Java proxy class will result in a NoSuchObject exception being throw. Unfortunately if the C++ object is deleted from C++ code, the Jaco interface has no way to know that the object has been deleted, and most likely the entire program will core dump.
To avoid this possibility it is possible to modify the C++ classes which will have Java proxies to extend JacoProxy. In this case when the C++ object is deleted, the Jaco manager will be informed, and the entry in the C++<-->Java map modified so that any future attempt to access the C++ object from Java will result in a NoSuchObject exception.
When used in this way all of the C++ (and any other native) code must be compiled and linked into one or more dynamic load libraries (typically .so file on Unix, and .dll files under Windows). These libraries are then loaded from Java using the System.loadLibrary() method. Once the native code is loaded new C++ objects can be created as described above.
The steps involved are:
Before invoking any Java code you must create an instance of JacoManager. When used in this way your C++ program will dynamically start the Java Virtual Machine (JVM) when JacoManager is created. You can specify the path to the JVM to be started, and the CLASSPATH to use, as arguments to JacoManager, otherwise default will be used.
Not yet supported.