Bi-directional conversion library6314429Abstract A bi-directional conversion library is provided for translating data structures used in a computer program from a first computer programming language to data structures used by a second computer programming language. In the preferred embodiment, a conversion library is provided for converting between Java.TM. and C. The conversion library of the present invention allows existing computer programs to be reused, thereby reducing the effort required to integrate newly written programs to existing systems. Claims What is claimed is: Description FIELD OF THE INVENTION
jstring createJavaString(
JNIEnv * env,
const char * cString );
The createJavaStringFromWide function creates a new Java.TM. string based on a wide C string passed as a parameter (i.e. a null-terminated array of unsigned short). This function is performed in a similar manner to the previously discussed createJavaString function and may be implemented by the following API:
jstring createJavaStringFromWide(
JNIEnv * env,
const unsigned short * cString );
The allocCString function creates a new C string based on a passed Java.TM. string object, and is the complement to the createcreateJavaString function. The returned string is declared to be a constant (const) since the string is allocated within the Java.TM. VM and therefore should not be modified. This is also consistent with the treatment of strings within Java.TM. where a Java.TM. string object is immutable. A representative API for allocating is as follows:
const char * allocCString(
JNIEnv * env,
jstring javaStr );
Since there is no garbage collection in C, all strings created with allocCString must be freed via a call to freeCString, which may be implemented by the following API:
void freeCString(
JNIEnv * env,
jstring javaStr,
const char ** stringToFree );
/* Note: pointer to a string */
The allocCWideString and freeCWideString functions perform analogous operations for wide C strings. The freeCString function takes a pointer to a string allocated via allocCString (const char **) as a parameter, not simply a string (const char *). This use of the pointer ensures that the freed string is not referenced a later time. Representative APIs for allocCWideString and freeCWideString are as follows:
const unsigned short * allocCWideString(
JNIEnV * env,
jstring javaStr );
void freeCWideString(
JNIEnv * env,
jstring javaStr,
const unsigned short ** stringToFree );
/* Note: pointer to a string */
The array functions provide means for converting between Java.TM. arrays and their C counterparts where both arrays of primitive data types and of objects are supported. Primitive data types are defined as data elements built-in to the computer language which represent a single piece of data (eg. a number). Examples of primitive data types include integers, float, and boolean. For the purposes of these functions, Java.TM. string objects are considered primitive data types, since a class description is not needed. Five functions are provided: createJavaPrimitiveArray, createJavaObjectArray, allocCPrimitiveArray, allocCStructureArray and freeCArray. The createJavaPrimitiveArray and createJavaObjectArray functions both create a Java.TM. array based on a C array passed in as a parameter. In each case, a size and type of the array must also be specified. In the case of creating an object array, a class descriptor for an associated class must also be provided. In a similar manner to Java.TM. string objects, Java.TM. arrays need not be freed, as they are garbage collected by the Java.TM. programming language. Representative APIs for this function are as follows:
jarray createJavaPrimitiveArray(
JNIEnv * env
char * arrayType,
void * cArray,
int cArrayLen );
jarray createJavaObjectArray(
JNIEnv * env
void * cArray,
int cArrayLen,
classDesc_t * classDesc );
The allocCPrimitiveArray and allocCStructureArray functions both create a C array based on a Java.TM. array passed as a parameter. The returned array is a copy of the associated Java.TM. array so that any changes made to this new C array are not reflected in the original Java.TM. array. For both functions, the type of array must be specified. In contrast to the Java.TM. array creation functions, the C array creation functions return the length of the allocated array via a numElements parameter. The allocCStructureArray function also requires the class descriptor describing the Java.TM. array elements passed as a parameter. Exemplary APIs for allocCPrimitiveArray and allocCStructureArray are as follows:
void * allocCPrimitiveArray(
JNIEnv * env
jarray javaArray,
char * arrayType,
int * numElements );
void * allocCStrucutreArray(
JNIEnv * env,
jarray javaArray,
char * arrayType,
classDesc_t * classDesc,
int * numElements );
As is also the case with the string functions, since C does not provide garbage collection, the freeCArray function must be called to release memory associated with the allocated C array. The freeCArray function may be implemented by the following API:
void freeCArray(
JNIEnv * env,
jarray javaArray,
char * arrayType,
void ** CArray );
The object/structure functions are at the core of the Bi-Directional Conversion Library according tot he present invention. These functions are used to convert between Java.TM. objects and C structures. Four object/structure functions are provided: java2c, c2java, createEmptyJavaObject, and createJavaObjectFromStruct. The java2c function fills a specified C structure with data contained in a Java.TM. object passed to the function according to an indicated class descriptor. An API for implementing the java2c function is as follows:
void java2c(
JNIEnv * env
jobject javaObj,
void * cStruct
classDesc_t * classDesc );
The c2java function performs the complementary action of copying the data within a C structure to a corresponding Java.TM. object according to an indicated class descriptor. A representative API for c2java is as follows:
void c2java(
JNIEnv * env,
jobject javaObj.
void * cStruct,
classDesc_t * classDesc );
It should be noted that the java2c and c2java functions of the preferred embodiment do not provide any facilities for converting static data members of a Java.TM. object. The design of class descriptors is set forth herein below for use with the java2c and c2java functions of the conversion library according to the invention. The following description is predicated on the assumption that legacy C structures already exist, and that data in these structures is required in the Java.TM. programs or objects to be converted. The following steps illustrate the process of creating a Java.TM. class to parallel a C structure and describing the Java.TM. class via a class descriptor. 1) Identify the required C data structure (at the time of its creation, the library of the present invention assumes that legacy C structures already exist--otherwise, C and Java.TM. structures can be developed in tandem, as would be understood by a person of ordinary skill in the art). 2) Create a Java.TM. class with data members in a one-to-one correspondence with the C data structure identified in step 1 (even though this may not result in the best object-oriented design). This class must have a public default constructor defined. The default constructor is a constructor for a Java.TM. object which does not take in any parameters. It should also be noted that data members must not be class variables (i.e. not static data members). Any access specifiers can be used for data members (e.g. they can be private, protected or public). 3) Define an array of field descriptors, with one entry per data member of the Java.TM. class created in Step 2. The following is a brief description of the information which must be defined: fieldName: name of a data member in the Java.TM. class fieldType: one of JTYPE_* as defined in java2c.h, discussed in greater detail below fieldOffset: an offset into the C structure of the associated field (use an "offsetof" macro provided by Microsoft's.TM. C compiler) maxElems: if fieldType is JTYPE_STRING or JTYPE_WSTRING, this is the maximum string length in characters if fieldType is JTYPE_ARRAY or JTYPE_VARRAY, this is the maximum number of elements in the array arraySizeoffset: if fieldType is JTYPE_VARRAY, this is the offset the field in the C structure which contains the actual number of elements in the array. This allows an array with a certain maxElems to be occupied by fewer elements, as specified in another field of the structure fieldClassDesc--if fieldType is JTYPE_OBJECT ( className ), JTYPE_ARRAY ( JTYPE_OBJECT ( className ) ), or JTYPE_VARRAY ( JTYPE_OBJECT ( className ) ), this is a pointer to the class for className 4) Define a class descriptor with the following information: className: the fully qualified Java.TM. class name using `/` as a class delimiter e.g. "ops/dbview/myDbclass" numfields: the number of fields in the field descriptor array size: the size of the assoicated `C` structure (use the "sizeof" macro). fields: the array of field descriptors from 3) An actual example of the steps involved in creating the Java.TM. class to parallel a following hypothetical C structure otherStruct_t and its corresponding otherClass is disclosed herein below:
typedef struct {
char someString [ MAX_STR_LEN + 1 ];
int numValues;
otherStruct_t values [ MAX_VALUES ];
} info_t;
The following Java.TM. class could be created (other methods can be added--only the data members matter for this library):
public class Info {
private String someString = null;
private int numValues = 0;
private otherClass [ ] values =
new otherClass [ MAX_VALUES ];
public Info()
{
// create otherClass objects in values array
}
}
The following exemplary fieldDesc_t (field descriptor array) and classDesc_t (class descriptor array) definitions are defined:
fieldDesc_t infoFields [ ] = {
{ "someString",
JTYPE_STRING,
offsetof ( info_t, someString ),
MAX_STR_LEN + 1,
0, // not applicable for this field type
NULL }, // not applicable for this field type
{ "numValues",
JTYPE_INT,
offset ( info_t, numValues ),
0, // not applicable for this field type
0, // not applicable for this field type
NULL }, // not applicable for this field type
{ "values",
JTYPE VARRAY ( JTYPE OBJECT ( "otherClass" )
),
offsetof ( info_t, values ),
MAX_VALUES,
offsetof ( info_t, numvalues ),
&classDescForOtherClass }
};
classDesc_t infoClassDesc = {
"Info",
sizeof ( infofields ) / sizeof ( fieldDesc_t
), // num fields
sizeof ( infor_t )
infoFields };
The createEmptyJavaObject function creates a new Java.TM. object of a specified class in a className parameter based on a default constructor. The data members of a newly created object are not assigned any values unless a default constructor performs initialization. A representative API for this function is as follows:
jobject createEmptyJavaObject(
JNIEnv * env
char * className );
The createJavaObjectFromStruct function creates a new Java.TM. object based on a specified class descriptor. The data members of the new Java.TM. object are initialized with the values contained in a C structure passed in as a cStruct parameter. The createJavaObjectFromStruct function may be implemented by the following API:
jobject createJavaObjectFromStruct(
JNIEnv * env,
void * cStruct,
classDesc_t * classDesc );
It should be noted that both of the createEmptyJavaObject and createJavaObjectFromStruct functions each create a Java.TM. object using a default constructor. The default constructor must be defined for all objects to be created via the conversion library DLL of the present invention. If a constructor other than the default constructor is required, the JNI NewObject function must be chosen. Often, not all of the data members of an object passed to a native method are required. The field accessor/mutator functions discussed below allow individual fields of an object to be read (via an accessor function) or modified (via a mutator function). None of these functions require a class descriptor to be defined. It should be noted that field accessor/mutator functions do not provide any facilities for accessing or changing static data members of a Java.TM. object. Two sets of accessor/mutator pairs are provided in accordance with the preferred embodiment: get<Primitve Type>Field/set<Primitive Type>Field and getObjectField/setObjectField. The get<Primitive Type>Field/set<Primitive Type>Field pair of functions provide means to access and modify primitive data members of a Java.TM. object based on their names. Each primitive type has its own pair of accessor/mutator functions, each of which returns a value of the appropriate C type. The supported types are summarized below:
<Primitive Type>
Field Type in Function Name Return/Parameter Type
JTYPE_INT Int int
JTYPE_LONG Long _int64
JTYPE_SHORT Short short
JTYPE_BYTE Byte char
JTYPE_WCHAR Wchar unsigned short
JTYPE_CHAR Char unsigned char
JTYPE_FLOAT Float float
JTYPE_DOUBLE Double double
JTYPE_BOOLEAN Boolean boolean
JTYPE_STRING String jstring
The string type is a special case, since in Java.TM. it is a class, where as in C it is a primitive array. The bi-directional conversion library of the present invention treats the string as a primitive type (since a class descriptor is not required), but the Java.TM. string value returned cannot be used directly by the Ccode. The allocCString and freeCString functions must be used to allocate and free C-style strings. It should be noted that primitive data types are basic field types such as boolean , integer or byte. The get<Primitive Type>Field/set<Primitive Type>Field functions may be implemented by the following exemplary APIs:
<Native Type> get <Primtive Type>Field(
JNIEnv * env,
jobject javaObj,
char * fieldName );
void set<Primitive Type>Field(
JNIEnv * env,
jobject javaObj,
char * fieldName,
<Native Type> value );
The getObjectfield and setObjectfield functions allow embedded objects to be accessed and modified. In addition to a field name in the Java.TM. object, the type of the object must also be specified. A JTYPE_OBJECT (className) macro can be used to formulate the type specifier. A skilled person will recognize that care should be taken when using the object accessor/mutator functions since the getObjectfield function returns a reference to an actual embedded object, and not a copy of the object. The setObjectField replaces the reference to an existing embedded object with a reference to the new copied object. Typical usage of these functions would include using the getObjectField to retrieve a reference to an object, and then to use the java2c, c2java or a field accessor/mutator pair to manipulate the data. Since a reference to an original object is used, the setObjectField function need not be called (since it would merely change the reference back to the same object). If a new object is created via the createEmptyJavaObject or createJavaObjectFromStruct functions, the setObjectfield function should be used to replace the existing embedded object with the new object. Exemplary APIs for the getObjectField and setObjectField functions are as follows:
jobject getObjectField(
JNIEnv * env,
jobject javaObj,
char * fieldName,
char * fieldType );
void setObjectField(
JNIEnv * env,
jobject javaObj,
char * fieldName,
char * fieldType,
jobject value );
It will be appreciated that, although one particular embodiment of the invention has been described in detail, various changes and modifications may be made. For example, in the mapping layer, the conversion functions could be directly integrated into legacy C code. Also, although not provided by the implementation set forth herein, the mapping of primitive data types may be included in the conversion. Although the preferred embodiment provides for embedded objects to be embedded within themselves alternative embodiments are contemplated which do not support embedded objects or reference them to external structures. With respect to the mapping of arrays, embodiments are possible which do not to provide array mapping functions or array accessor/mutator functions. It is contemplated that access may be provided to Java.TM. Object Methods, as would be understood by a person of ordinary skill in the art. Furthermore, although the detailed description of the preferred embodiment herein above is limited to a discussion of the conversion between Java.TM. and C, it will be appreciated that conversions are possible between any two different computer languages according to the principles of the present invention, and in particular C can be converted into Java.TM.. All such changes and modifications may be made without departing from the sphere and scope of the invention as defined by the claims appended hereto.
|
Same subclass Same class Consider this |
||||||||||
