Codemesh Runtime v3 C++ API Reference
3.9.205
|
Classes | |
class | xmog_peer |
A utility class that provides access to the Java interface com.codemesh.peer.PeerType. More... | |
class | xmog_peer_value |
The wrapper class for the builtin Java com.codemesh.peer.Value type. More... | |
class | xmog_serializable |
A utility class that provides easy access to the Java type com.codemesh.peer.SerializablePeer. More... | |
Typedefs | |
typedef void *(XMOG_CALLING_CONVENTION * | XMOG_PEER_UNMARSHAL_METHOD) (xmog_base &peer, xmog_java_class *peerClass, const char *cppType, xmog_localenv *env) |
The peer unmarshalling callback. More... | |
typedef jint(JNICALL * | XMOG_CALLBACK_METHOD) (xmog_base &peer, jlong pInst, xmog_peer_value &retexc, xmog_java_array_template< xmog_peer_value > &args, xmog_localenv *env) |
The callback function type. More... | |
typedef jint(JNICALL * | XMOG_CALLBACK_OBJECT_ARG_METHOD) (xmog_base &peer, jlong pInst, xmog_peer_value &retexc, jobject arg, xmog_localenv *env) |
The optimized one-argument callback function type. More... | |
Functions | |
virtual xmog_java_class * | xmog_base::xmog_get_java_peer (xmog_localenv *env=NULL) |
Returns NULL if the type does not have a Java peer type, a pointer to the type's xmog_java_class otherwise. More... | |
virtual int | xmog_base::xmog_create_java_peer (xmog_java_class *clazz, xmog_localenv *env=NULL, xmog_flags flags=xmog_base::GLOBAL) |
Creates a Java peer instance for this type. More... | |
virtual int | xmog_base::xmog_to_java_peer (xmog_localenv *env=NULL) |
Sets the native instance's state into the Java peer instance. More... | |
Java peers are an advanced feature that was introduced with version 3.0 of Codemesh's Java/C++ integration product. Under most circumstances, a C++ developer will only use the generated C++ proxy classes. Under some circumstances though, it might be
necessary or desirable for a C++ developer to extend the generated proxy types on the native side.
For example, you might have generated a proxy type for the java.io.Serializable
interface and you wish to create C++ implementations of that interface. Of course you would expect that the data that these C++ types contain will get serialized when you pass an instance of your custom C++ type to a Java output stream.
This is of course not what's going to happen unless you help the framework a little bit. You will need to make sure that a C++ instance knows which information to stash into a Java object in which way. In the general case, your C++ instance will also need to know what Java type is its peer type.
Let's take the example from above and define a C++ type that we wish to use with Java. The following snippet omits all the usual things like constructors, destructor, or methods and just focuses on the data declarations.
Clearly, the C++ fields are totally unknown to the Java side and will consequently not be serialized when this object is written to a Java stream. In order to solve this problem, there are three problems that need to be solved:
Serializable
instance can be used and that can hold the data from the C++ sideThese three tasks are achieved with the help of three framework methods declared by the xmog_base class. In general, you will have to provide at least the first and the third method and can use the second method that is provided by the default implementation.
Let's extend the above example by providing the necessary framework method to allow a developer to use the MySerializable
type as expected:
In the above snippet, the first method indicates that we wish to use the built-in utility type xmog_serializable as the Java peer, but you could use your own Java peer types as well.
In the second method, we copy the C++ instance's data into the peer instance by using the instance's hashtable to hold the data with the field names as keys. We could also have chosen to use a binary data representation for the C++ data, which would probably give us higher performance, but also put a bigger implementation burden on us.
What do you have to do when you have an inheritance hierarchy on the C++ side? You simply override the xmog_java_to_peer method and have it call its superclass' implementation as the very first thing:
It is a little wasteful to override the typeinfo assignment in the derived type but in the larger scheme that should hardly matter all too much.
The above example illustrates the peer framework usage for the common example of a java.io.Serializable
peer. In general, you can use the xmog_peer utility type to get access to an xmog_java_class instance and to methods that allow you to invoke all com.codemesh.peer.PeerType interface methods to get and set data from and to a peer instance. Here's an example of a custom peer type:
One question that we glossed over a little bit is what the Java peer type should look like and where it is coming from. The latter question is easy to answer: you can deploy the peer type with the other Java classes that make up your application. The former question is a little more complex to answer. In the above example, we used the scenario where the user wanted to implement the java.io.Serializable
interface in C++. This is something that Codemesh has come to understand as a pretty basic requirement and we have therefore created a peer type for just that purpose. That peer type is tucked away in the runtime library and injected into the JVM when required. You can use this peer type in all scenarios where the Java peer instance is used in a place that expects a java.io.Serializable
or a java.lang.Object
instance. You cannot use that peer type in scenarios where the Java side would expect any other types. You have to create your own peer types to accommodate these otehr scenarios.
It's completely up to you on how these peer types store the information, but if your peer types implement the com.codemesh.peer.PeerType
interface you can use the xmog_peer utility class from your C++ application. This can make your implementation task much easier because you don't have to worry about using a custom Java type from C++ and you don't have to create custom integration infrastructure which you will need to maintain. Several implementations of peer types for commonly used interfaces are available as part of the com.codemesh.peer package and there is also an abstract class that you can use as the basis for your specific interface implementation.
If it is your intent to also use the supplied peer types from a Java application, you can deploy the xmog_peer.jar
file as part of your Java application.
xmog_peer.jar
file as part of your C++ application. All supplied peer types are available via the runtime library. typedef jint(JNICALL * XMOG_CALLBACK_METHOD) (xmog_base &peer, jlong pInst, xmog_peer_value &retexc, xmog_java_array_template< xmog_peer_value > &args, xmog_localenv *env) |
The callback function type.
This is the prototype of the function that is called by the universal callback entry point. Every callback corresponds with one such method. This method then typically delegates to a virtual instance method on the instance represented by pInst. It should be noted that it is not required that the callback method be implemented in this fashion even though the code generator only generates code in this fashion. A callback could theoretically be implemented without any further delegation to an instance method.
peer | the Java object acting as a stand-in for the callback receiver. |
pInst | an integer that typically holds a pointer to a C++ object to whose instance method we delegate. |
retexc | an instance that will hold the result or the exception that was thrown during callback execution. |
args | the array of arguments that are passed to the callback. |
env | the local call environment. |
typedef jint(JNICALL * XMOG_CALLBACK_OBJECT_ARG_METHOD) (xmog_base &peer, jlong pInst, xmog_peer_value &retexc, jobject arg, xmog_localenv *env) |
The optimized one-argument callback function type.
This is the prototype of the function that is called by the universal callback entry point in the case of one reference type argument.
Every such callback corresponds with one such method. This method then typically delegates to a virtual instance method on the instance represented by pInst. It should be noted that it is not required that the callback method be implemented in this fashion even though the code generator only generates code in this fashion. A callback could theoretically be implemented without any further delegation to an instance method.
peer | the Java object acting as a stand-in for the callback receiver. |
pInst | an integer that typically holds a pointer to a C++ object to whose instance method we delegate. |
retexc | an instance that will hold the result or the exception that was thrown during callback execution. |
arg | the one reference-type argument being passed to the callback. |
env | the local call environment. |
typedef void*(XMOG_CALLING_CONVENTION * XMOG_PEER_UNMARSHAL_METHOD) (xmog_base &peer, xmog_java_class *peerClass, const char *cppType, xmog_localenv *env) |
The peer unmarshalling callback.
This is the prototype of the function that is called when a returned Java object is a peer type that needs to be converted back to a C++ object. Clearly, the returned C++ object needs to be dynamically allocated and we can only return it through a void *
because we know absolutely nothing about it.
In theory, we only need to pass the Java object reference to the unmarshalling method because we've already identified the proper unmarshalling method and it should know how to deal with the Java object. In practice, you might wish to have one peer unmarshalling method that knows how to deal with a variety of C++ types. To support this scenario, the unamrshalling method is also provided with access to the Java peer class and the retrieved C++ typename, thereby saving another query.
A typical implementation of the unmarshalling method follows the following blueprint:
Here's an example:
In the above exmaple, we show how the C++ type identifier is used to distinguish between two different C++ types that are handled by the same unmarshaller. If the unmarshaller returns NULL
, it did not handle the C++ type and the runtime will look for another unamrshaller that might.
peer | the Java peer object. |
peerClass | the Java class of the peer object. |
cppType | the C++ type identifier. |
env | the local call environment. |
|
virtual |
Creates a Java peer instance for this type.
This method is implemented to return an instance of Codemesh's Serializable
type. The Serializable
type supports storage of
This method will only be called under the following circumstances:
NULL
reference.NULL
.This method is part of the Java Peer Framework.
clazz | the peer class we need to instantiate. |
env | the local call environment. The default value is NULL . |
flags | the flags governing reference type and other housekeeping information. The default value is xmog_base::GLOBAL. |
|
virtual |
Returns NULL
if the type does not have a Java peer type, a pointer to the type's xmog_java_class otherwise.
A user-written native type that needs to be represented by a specific Java peer type should override this method to return a
pointer to that type's xmog_java_class. Generated proxy classes inherit the default implementation which always returns NULL
.
env | the local call environment. May be NULL . |
NULL
if the type does not have to instantiate a Java peer type, a pointer otherwise.
|
virtual |
Sets the native instance's state into the Java peer instance.
This method needs to be overridden in order to set native information into the Java peer instance. There are two separate methods for creation and "serialization" with the latter being handled by this method.
The default implementation of this method does nothing. Your native type needs to override this method to set the instance's C++ data into the Java peer instance.
env | the local call environment. May be NULL . |