Codemesh Runtime v3 C++ API Reference  3.9.205
Classes | Typedefs | Functions
Java Peer Framework

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_classxmog_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...
 

Detailed Description

Introduction

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.

Using C++ types with the framework

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.

class MySerializable : public java::io::Serializable
{
private:
int anIntField;
long aLongField;
char* aStringField;
};

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:

  1. we need to make available a Java type that can be used in any place where a Java Serializable instance can be used and that can hold the data from the C++ side
  2. we need to create an instance of that Java type
  3. we need to copy the C++ data into the newly created Java instance so that the Java serialization framework can take advantage of the information

These 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:

xmog_java_class * MySerializable::xmog_get_java_peer( xmog_localenv * env )
{
return clazz;
}
int MySerializable::xmog_to_java_peer( xmog_localenv * env )
{
xmog_serializable::set_typeInfo( this, "MySerializable", env );
xmog_serializable::set_int( this, "anIntField", anIntField, env );
xmog_serializable::set_long( this, "aLongField", aLongField, env );
xmog_serializable::set_Object( this, "aStringField", aStringField, env );
return 0;
}

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:

int MySubSerializable::xmog_to_java_peer( xmog_localenv * env )
{
this->MySerializable::xmog_to_java_peer( env );
//override the typeinfo so that we know that this is a derived object
xmog_serializable::set_typeInfo( this, "MySubSerializable", env );
xmog_serializable::set_int( this, "anotherIntField", anotherIntField, env );
xmog_serializable::set_long( this, "anotherLongField", anotherLongField, env );
return 0;
}

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:

xmog_java_class * MySerializable::xmog_get_java_peer( xmog_localenv * env )
{
static xmog_java_class * clazz = xmog_peer::get_class( "com.biz.MyPeerType", env );
return clazz;
}
int MySerializable::xmog_to_java_peer( xmog_localenv * env )
{
xmog_peer::set_typeInfo( this, "MySerializable", env );
xmog_peer::set_binaryData( this, "xcvfg", 5, env );
return 0;
}

Java Peer Type Requirements

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.

Note
It is not necessary to deploy the xmog_peer.jar file as part of your C++ application. All supplied peer types are available via the runtime library.

Typedef Documentation

◆ XMOG_CALLBACK_METHOD

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.

Parameters
peerthe Java object acting as a stand-in for the callback receiver.
pInstan integer that typically holds a pointer to a C++ object to whose instance method we delegate.
retexcan instance that will hold the result or the exception that was thrown during callback execution.
argsthe array of arguments that are passed to the callback.
envthe local call environment.

◆ XMOG_CALLBACK_OBJECT_ARG_METHOD

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.

Parameters
peerthe Java object acting as a stand-in for the callback receiver.
pInstan integer that typically holds a pointer to a C++ object to whose instance method we delegate.
retexcan instance that will hold the result or the exception that was thrown during callback execution.
argthe one reference-type argument being passed to the callback.
envthe local call environment.

◆ XMOG_PEER_UNMARSHAL_METHOD

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:

  • create a heap-allocated C++ instance using the "from existing Java object" constructor
  • call xmog_peer helper methods to extract the data from the Java object and set it into the C++ object
  • return the C++ instance

Here's an example:

void * XMOG_CALLING_CONVENTION myUnmarshaller( xmog_base & peer, xmog_java_class * peerClass,
const char * cppType, xmog_localenv * env )
{
xmog_base * result = NULL;
if( !strcmp( cppType, "type1" ) )
{
result = new MyType( peer.get_jobject_( env ), xmog_base::GLOBAL );
xmog_peer::get_int( result, "age", &result->age, env );
xmog_peer::get_int( result, "id", &result->id, env );
}
else if( !strcmp( cppType, "type2" ) )
{
result = new TotallyDifferentType( peer.get_jobject_( env ), xmog_base::GLOBAL );
MyDataStruct data;
xmog_peer::get_binaryData( result, (jbyte*)&data, sizeof(data), env );
result->setAge( data.age );
result->setID( data.id );
}
return result;
}

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.

Parameters
peerthe Java peer object.
peerClassthe Java class of the peer object.
cppTypethe C++ type identifier.
envthe local call environment.

Function Documentation

◆ xmog_create_java_peer()

virtual int xmog_base::xmog_create_java_peer ( xmog_java_class clazz,
xmog_localenv env = NULL,
xmog_flags  flags = xmog_base::GLOBAL 
)
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

  • native type information
  • binary data
  • typed field data (name/value pairs in a Hashtable)

This method will only be called under the following circumstances:

  • the proxy instance is a stand-alone NULL reference.
  • the xmog_get_java_peer() method for the type returns non-NULL.

This method is part of the Java Peer Framework.

Parameters
clazzthe peer class we need to instantiate.
envthe local call environment. The default value is NULL.
flagsthe flags governing reference type and other housekeeping information. The default value is xmog_base::GLOBAL.
Returns
0 if the method completed OK, -1 if an error occurred.

◆ xmog_get_java_peer()

virtual xmog_java_class* xmog_base::xmog_get_java_peer ( xmog_localenv env = NULL)
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.

Parameters
envthe local call environment. May be NULL.
Returns
NULL if the type does not have to instantiate a Java peer type, a pointer otherwise.

◆ xmog_to_java_peer()

virtual int xmog_base::xmog_to_java_peer ( xmog_localenv env = NULL)
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.

Parameters
envthe local call environment. May be NULL.
Returns
0 if the method completed OK, -1 if an error occurred.
xmog_serializable::get_class
static xmog_java_class * get_class()
Returns a pointer to the xmog_java_class that represents the Codemesh Serializable class.
xmog_peer::set_long
static int set_long(xmog_base *peer, const char *fieldNameUtf, jlong l, xmog_localenv *env=NULL)
Sets a long field into the instance.
xmog_peer::get_int
static int get_int(xmog_base *peer, const char *fieldNameUtf, jint *i, xmog_localenv *env=NULL)
Reads an int field from the instance.
xmog_base::get_jobject_
virtual jobject get_jobject_(xmog_localenv *env=NULL) const
Returns this instance's object reference.
xmog_peer::set_typeInfo
static int set_typeInfo(xmog_base *peer, const char *typeInfoUtf, xmog_localenv *env=NULL)
Sets the typeinfo for the C++ instance that is storing data into this instance.
xmog_base
The baseclass for all proxy types in the framework.
Definition: xmog_base.h:29
xmog_localenv
A class representing per-thread information for the integration runtime.
Definition: xmog_localenv.h:32
xmog_peer::set_binaryData
static int set_binaryData(xmog_base *peer, jbyte *pBytes, size_t len, xmog_localenv *env=NULL)
Sets binary data into the instance.
xmog_java_class
A C++ wrapper for Java types.
Definition: xmog_java_class.h:31
xmog_peer::get_binaryData
static int get_binaryData(xmog_base *peer, jbyte **ppBytes, size_t *len, xmog_localenv *env=NULL)
Retrieves binary data from the instance.
xmog_peer::set_int
static int set_int(xmog_base *peer, const char *fieldNameUtf, jint i, xmog_localenv *env=NULL)
Sets a int field into the instance.
xmog_peer::set_Object
static int set_Object(xmog_base *peer, const char *fieldNameUtf, jobject o, xmog_localenv *env=NULL)
Sets an Object field into the instance.
xmog_peer::get_class
static xmog_java_class * get_class()
Returns a pointer to the xmog_java_class that represents the com.codemesh.peer.PeerType interface.

Copyright (c) 1999-2020 by Codemesh, Inc., ALL RIGHTS RESERVED.