Method and system of custom marshaling of inter-language parameters6167565Abstract A computer-based custom marshaling method and system for custom marshaling of parameters during invocation of functions implemented in a second language by computer programs implemented in an first language. The parameter to be custom marshaled has a first type in the first language and a second type in the second language. The custom marshaling system receives code for converting a parameter of the first type to a parameter of the second type and for converting a parameter of the second type to a parameter of the first type. The custom marshaling system monitors the execution of a computer program implemented in the first language that invokes a function implemented in the second language. The invocation passes a parameter of the first type, and the function expects a parameter of the second type. The custom marshaling system intercepts the invocation of the function implemented in the second language. After intercepting the invocation, the custom marshaling system executes the received code for converting the passed parameter of the first type to a parameter of the second type. The custom marshaling system then invokes the function implemented in the second language passing the parameter converted to the second type. The invoked function returns a parameter of the second type. After invocation of the function, the custom marshaling system executes the received code for converting the returned parameter of the second type to a parameter of the first type and returns the converted parameter of the first type when returning from the intercepted invocation of the function. Claims What is claimed is: Description TECHNICAL FIELD
TABLE 1
______________________________________
COM Prototype Java Prototype
______________________________________
Foo ([in] COMTYPE) Foo (JAVATYPE)
Foo ([out,retval] COMTYPE*)
JAVATYPE Foo( )
Foo ([in] COMTYPE*) Foo (JAVATYPE)
Foo ([out] COMTYPE*) Foo (JAVATYPE)*
Foo ([in,out] COMTYPE*)
Foo (JAVATYPE)*
Foo ([out,retval] COMTYPE**)
JAVATYPE Foo ( )
Foo ([in] COMTYPE**) Foo (JAVATYPE[ ])
Foo ([out] COMTYPE**)
Foo (JAVATYPE[ ])
Foo ([in,out] COMTYPE**)
Foo (JAVATYPE[ ])
______________________________________
*If the JAVATYPE is immutable, then the JAVATYPE is passed as an array so
that a value can be returned. Immutability of a parameter type can be
specified when the custom marshaling code is identified to the custom
marshaling system.
Table 1 illustrates the mapping of the COM prototypes to the Java prototype. The custom marshaling system generates Java prototypes based on the direction in which the parameter is to be passed (e.g., [in] and [out]), whether the parameter is passed in by single or double indirection. In the following, "JAVATYPE" refers to the type of the Java parameter, "COMTYPE" refers to the type of the COM parameter, and "Foo" refers to the function to be invoked. Unless specified otherwise, JAVATYPE is the type of an object, and the object is passed by reference. As shown in Table 1, when the COMTYPE specifies double indirection, then the JAVATYPE is an array to effect the double indirection. FIG. 1 is a block diagram illustrating components of a computer system upon which the custom marshaling system may be implemented. The computer system 100 includes a central processing unit 101, memory 102, and I/O devices 103. The memory contains a Java VM 104, a custom marshaling map 105, Java code 106, COM functions 107, marshaling classes 108, and Java functions 109. The custom marshaling map contains a mapping from the Java data types to COM data types, identifies the marshal classes that defines the marshaling code, and indicates whether the JAVATYPE is immutable. The marshaling classes are provided by a programmer and define the custom marshaling code. The Java VM loads and executes the Java program, which invokes a COM function. A COM function in turn may invoke a Java function. The parameters passed by the COM function may also need to be converted. Therefore, the marshal classes define various methods for converting to and from JAVATYPE and COMTYPE. The methods of the marshaling classes perform appropriate converting of data types and allocating and deallocating of memory as needed. The following lists various methods of the marshaling classes and description of the behavior of each method. The methods toJava, toUninitJava, toExtemal, and toUninitExternal create new instances of the parameters. The methods copyToJava and copyToExternal propagate their converted values to existing instances. JAVATYPE toJava (COMTYPE ppCOMPTYPE) This method creates an instance of JAVATYPE, converts the COMTYPE parameter pointed to by ppCOMTYPE to a JAVATYPE and returns the JAVATYPE instance set to the converted value as the return value of the method. This method is used when a COM program is passing an [in] parameter to invoke a Java function or when a COM function is returning a [retval] parameter to a Java program. This method creates an initialized JAVATYPE instance that is passed to a Java program or function. VOID copyToJava (JAVATYPE valueJAVATYPE, COMPTYPE ppCOMTYPE) This method converts the COMTYPE parameter pointed to by ppCOMTYPE to a JAVATYPE and stores the converted value in the parameter valueJAVATYPE. This method is used when returning an [out] parameter to a Java program from an invoked COM function. This method is used to change the value of an existing actual parameter in the Java program; this method does not create a new instance of JAVATYPE. JAVATYPE toUninitJava (COMPTYPE ppCOMTYPE) This method creates an uninitialized JAVATYPE instance and returns it as the return parameter. This method is used when a COM program is passing an [out] parameter to a Java function. The unitialized JAVATYPE instance is passed to the Java function. VOID copyToExternal (JAVATYPE valueJAVATYPE, COMTYPE ppCOMTYPE) This method converts the JAVATYPE parameter to a COMTYPE and stores the converted value in ppCOMTYPE. This method is used when a Java program passes a parameter to a COM function or when a Java function returns an [out] parameter to a COM program. This method is used to change the value of an existing actual parameter; this method does not create a new instance of a COMTYPE. This method is invoked, for example, when an instance of the COMTYPE parameter is allocated in the stack. VOID relcascByValExternal (COMTYPE ppCOMTYPE) This method releases resources used by the COMTYPE parameter, but this method does not release the instance. This method is invoked, for example, when the instance is allocated on the stack. This method is used when a COM function returns to a Java program and the COM parameter had a size designated by the marshaling code. VOID toExternal (JAVATYPE valueJAVATYPE, COMTYPE ppCOMTYPE) This method creates a new instance of COMTYPE, converts the valueJAVATYPE to a COMTYPE, and stores the converted value as the new COMTYPE instance. This method is used when a Java function returns a return value to a COM program. VOID releaseExternal (COMTYPE ppCOMTYPE) This method releases resources used by the COMTYPE parameter and releases the instance of the parameter. The method is used when a Java program invokes a COM function and the COM function expects an [out] parameter. This method is used in conjunction with the toExternal and toUninitExternal methods. VOID toUninitExternal (JAVATYPE value JAVATYPE) This method creates a new instance of COMTYPE. This method is used when a JAVA program invokes a COM function that has an [out] parameter. Tables 2-5 contain various marshaling sequences used with custom marshaling of paraneters. Each table contains two subtables. The first subtable indicates the sequence when a Java program invokes a COM function, and the second subtable indicates the sequence when a COM program invokes a Java function. Table 2 lists marshaling sequences when the COMTYPE is passed by reference and the JAVATYPE is mutable. Each subtable contains four rows indicating the code execution sequences for the direction (i.e., [in], [out], [in,out], and [out,retval]) that the parameter passed to the COM function. Also, the subtables contain "preferred" and "alternate" sequences. In this table, if the marshaling class exports a "ByValSize" variable and a copyToExternal method, then the preferred sequence is used. If the "ByValSize" variable is exported, then custom marshaling system can allocate the variable of that size on the stack. The example COM finction is named "Foo," and the example Java function is named "foo." For example, the preferred marshaling sequence when a Java Program invokes a COM function and passes an [in,out] parameter is copyToExternal Foo copyToJava releaseByValExternal When this Java VM detects such an invocation, the Java VM allocates space on the stack for the parameter (i.e., "ByValSize" number of bytes) and then invokes the copyToExternal method. This method converts the JAVATYPE to a COMTYPE and copies the converted value to the allocated space on the stack. The Java VM then invokes the COM function Foo. On return, the Java VM invokes the copyToJava method to convert the COMTYPE returned on the stack to a JAVATYPE and stores the converted value in the JAVATYPE parameter passed by the Java program. The Java VM then invokes the releaseByValExternal method to perform any cleanup needed by the COMTYPE. The Java VM then deallocates the space on the stack and returns the Java program. When a COM program invokes a Java function and passes an [in,out] parameter, the marshaling sequence as indicated by Table 2 is toJava releaseByValExternal foo copyToExternal The Java function has a COM wrapper function which the COM program invokes. When the COM wrapper function is invoked, it performs this marshaling sequence. The COM wrapper function first calls the toJava method to convert the COMTYPE to a JAVATYPE and return the JAVATYPE as the return value of the function. The COM wrapper function then invokes the releaseByValExternal method to perform any clean up for the COMTYPE parameter. The COM wrapper function then invokes the Java function foo passing the JAVATYPE parameter. When the Java function returns, the COM wrapper function invokes the copyToExternal method to convert the JAVATYPE to a COMTYPE and to store the converted value as the [out] parameter on the stack. The COM wrapper function then returns to the COM function.
TABLE 2
______________________________________
C prototype Java prototype
Foo(COMTYPE*) foo(JAVATYPE)
Direction Preferred Alternate
______________________________________
Java invokes COM
[IN] copyToExternal toExternal
Foo Foo
releaseByValExternal
releaseExternal
[OUT] Foo toUninitExternal
copyToJava Foo
releaseByValExternal
copyToJava
releaseExternal
[IN,OUT] copyToExternal toExternal
Foo Foo
copyToJava copyToJava
releaseByValExternal
releaseExternal
[OUT,RETVAL] Foo
toJava
releaseExternal
COM invokes Java
[IN] toJava
foo
[OUT] toUninitJava
foo
copyToExternal
[IN,OUT] toJava
releaseByValExternal
foo
copyToExternal
[OUT,RETVAL] Foo
toExternal
______________________________________
Table 3 lists marshaling sequences when the COMTYPE is passed by reference and the JAVATYPE is immutable. In such a situation, the JAVATYPE parameter is passed as an array, so that it can be modified. The preferred marshaling sequence for an [in,out] parameter when a Java program invokes a COM program is copyToExternal Foo toJava releaseByValExternal. The sequence is similar to the corresponding sequence of Table 2, except that the toJava method is invoked rather than the copyToJava method. The toJava method creates a new JAVATYPE instance, rather than modifying an existing JAVATYPE instance. This allows the newly created variable to be returned through the array mechanism.
TABLE 3
______________________________________
C prototype Java prototype
Foo(COMTYPE*) foo(JAVATYPE[])
Marshaling
Direction Preferred Alternate
______________________________________
Java invokes COM
[IN] copyToExternal toExternal
Foo Foo
releaseByValExternal
releaseExternal
[OUT] Foo toUninitExternal
toJava Foo
releaseByValExternal
toJava
releaseExternal
[IN,OUT] copyToExternal toExternal
Foo Foo
toJava toJava
releaseByValExternal
releaseExternal
COM invokes Java
[IN] toJava
foo
[OUT] foo
copyToExternal
[IN,OUT] toJava
releaseByValExternal
foo
copyToExternal
______________________________________
Table 4 lists marshaling sequences when the COM parameters are passed by value. The marshaling sequence when a Java program invokes a COM function passing an [in] parameter is copyToExternal Foo releaseByValExternal The COMTYPE parameter that is passed to the copyToExtemal method is allocated in the stack.
TABLE 4
______________________________________
C prototype Java prototype
Foo(COMTYPE) foo(JAVATYPE)
Marshaling
Direction Preferred Alternate
______________________________________
Java invokes COM
[IN] copyToExternal
Foo
releaseByValExternal
[OUT,RETVAL] Foo
toJava
releaseByValExternal
COM invokes Java
[IN] toJava
foo
[OUT,RETVAL] foo
copyToExternal
______________________________________
Table 5 lists marshaling sequences used when the parameter is designated as being passed by reference via double indirection. The marshaling sequence when a Java program invokes a COM function passing an [in] parameter is copyToExternal Foo releaseByValExternal.
TABLE 5
______________________________________
C prototype Java prototype
Foo(COMTYPE**) foo(JAVATYPE[])
Marshaling
Direction Preferred Alternate
______________________________________
Java invokes COM
[IN] toExternal
Foo
releaseExternal
[OUT] Foo
toJava
releaseExternal
[IN,OUT] toExternal
Foo
toJava
releaseExternal
COM invokes Java
[IN] toJava
Foo
[OUT] Foo
toExternal
[IN,OUT] toJava
releaseExternal
Foo
toExternal
______________________________________
FIG. 2 is a flow diagram illustrating the processing of the Java VM when it encounters an invocation to a COM function. In step 201, if the Java instruction currently being processed indicates to invoke a COM function, then the Java VM continues at step 202, else the Java VM continues with its normal processing. In step 202, if custom marshaling has been defined for a parameter, then the Java VM continues at step 203, else the Java VM continues at step 204. In step 203, the Java VM invokes a routine to perform custom marshaling of the parameters and then the Java VM continues its normal processing. In step 204, the Java VM invokes a routine to perform standard marshaling of the parameters and then the Java VM continues its normal processing. FIG. 3 is a flow diagram of the routine to custom marshal the parameters. In step 301, the routine retrieves information from the parameter to be custom marshaled. In step 302, if stubs have already been created for this parameter, then the routine continues at step 304, else the routine continues at step 303. In step 303, the routine invokes a subroutine to create the stubs (an in stub and an out stub) to control the marshaling. In step 304, the routine executes the in stub for the parameters. In step 305, the routine invokes the COM function. In step 306, the routine executes the out stub for this COM function and returns. FIG. 4 is a flow diagram of a subroutine that creates the in stub and the out stub. In steps 401-407, the subroutine loops selecting each of the parameters that are to be passed. In step 401, the routine selects the next parameter starting with the first. In step 402, if all the parameters have already been selected, then the subroutine returns, else the subroutine continues at step 403. In step 403, if the selected parameter is to be custom marshaled, then the subroutine continues at step 404, else the subroutine continues at step 406. In step 404, the routine adds the custom marshaling code to marshal the selected parameter to the in stub. In step 405, the routine adds the custom code to marshal back the selected parameter to the out stub and loops to step 401 to select the next parameter. In step 406, the routine adds code to pass the parameter to the in stub. In step 407, the routine adds code to return the parameter to the out stub and loops to step 401 to select the next parameter. FIG. 5 is a flow diagram of a COM wrapper function for a Java function. When code implemented in COM invokes a Java function, this COM stub is invoked. In step 501, the wrapper function marshals the parameter from the COM to the Java and returns. The following lists sample pseudocode implementation of marshaling classes. Code Table 1 lists the methods of a marshaling class for marshaling a JAVATYPE of double to a COMTYPE of "Fixed." The JAVATYPE of double is a primitive type in Java and is therefore immutable.
______________________________________
CODE TABLE 1
______________________________________
struct FIXED {
WORD fract;
short value;
} FIXED;
public FixedPtMarshaler {
public static int cbByValSize; // set of sizeof(FIXED) = 8
public static double toJava(int ppFIXED, int flags)
{
// convert **ppFIXED to a double
// return the double
}
public static void copyToExternal(double javaval,
int ppFIXED,
int Flags)
{
// convert double to a FIXED
// copy the FIXED to **ppFIXED
}
______________________________________
Code table 2 lists the pseudocode methods of a marshaling class for marshaling a JAVATYPE of string to a COMTYPE of "variant." The lo JAVATYPE of string is a primitive type in Java and is therefore immutable. The releaseByValExternal allows deallocation of resources for a parameter that was allocated in the stack.
______________________________________
CODE TABLE 2
______________________________________
struct {
short vt;
// Always VT.sub.-- BSTR for this example
short unused;
short unused1;
short unused2;
BSTR bstrVal;
// Points to characters in BSTR
long unused3;
// never used in this example.
} VARIANT;
public VarStrMarshaler {
public static int cbByValSize; // set of sizeof(VARIANT) = 16
public static String toJava(int ppVARIANT, int flags)
{
// convert **ppVARIANT to a String
// return the String
}
public static void copyToExternal(String javaval,
int ppVARIANT,
int Flags)
{
// convert String to a VARIANT
// copy the VARIANT to **ppVARIANT
}
public static void releaseByValExternal(int ppVARIANT, int Flags)
{
SysStringFree( (*ppVARIANT) - >bstrVal );
}
______________________________________
Code Table 3 lists pseudocode for methods of a marshaling class for marshaling a JAVATYPE of point object to a COMTYPE of point. The point object is mutable in Java. The copyToJava and to Uninitjava methods allows mutable objects to be passed using the non-array form.
______________________________________
CODE TABLE 3
______________________________________
//JAVATYPE
double ad1[ ] = {0};
double ad2[ ] = {0};
func(ad1, ad2);
System.out.println("func gave back: " + ad1[0] + ", " + ad1[1]);
}
public PointMarshaler {
public static int cbByValSize; // set of sizedof(POINT) = 8
public static Point toJava(int ppPOINT, int flags)
{
// convert **ppPOINT to a Point
// return the Point
}
public static void copyToExternal(Point javaval,
int ppPOINT,
int Flags)
{
// convert Point to a POINT
// copy the POINT to **ppPOINT
}
public static void copyToJava(Point javaval, int ppPOINT, int Flags)
{
// modify "javaval" in place so it is "equivalent" to **ppPOINT;
}
public static Point toUninitJava(int ppPOINT, int flags)
{
// create a new Point with arbitrary x and y values.
// the contents of **ppPOINT are completely undefined and
// should be ignored for fixed-size hook classes.
}
}
______________________________________
Code Table 4 lists pseudocode for methods of a marshaling class for marshaling when a COMTYPE needs to allocate and deallocate memory other than on the stack.
______________________________________
CODE TABLE 4
______________________________________
public RectMarshaler {
public static int cbByValSize; // set of sizeof(RECT) = 8
public static Rect toJava(int ppRECT, int flags)
{
.backslash..backslash. convert **ppRECT to a Rect
.backslash..backslash. return the Rect
}
public static void copyToExternal(Rect javaval,
int ppRECT,
int Flags)
{
.backslash..backslash. convert Rect to a RECT
.backslash..backslash. copy the RECT to **ppRECT
}
public static void toExternal(Rect javaval, int ppRECT, int Flags)
{
.backslash..backslash. allocate a new RECT, initialize it using
javaval,
.backslash..backslash. store pointer in *ppRECT
}
public static void releaseExternal(int ppRECT, int Flags)
{
.backslash..backslash. release *ppRECT. If RECT required a
releaseByValExternal
.backslash..backslash. (which it doesn't), this routine must do that
work as well.
}
______________________________________
Code Table 5 lists pseudocode for methods of a marshaling class for marshaling when the COMTYPE is of variable size.
______________________________________
CODE TABLE 5
______________________________________
public AnsiMarshaler {
public static String toJava(int ppCHAR, int flags)
{
// convert **ppCHAR to a String
// return the String
}
public static void toExternal(String javaval, int ppCHAR, int Flags)
{
// allocate a new LPSTR, initialize it using javaval,
// store pointer in *ppCHAR
}
public static void releaseExternal(int ppCHAR, int Flags)
{
// release *ppCHAR. If LPSTR required a
// releaseByValExternal (which it doesn't), this routine
// must do that work as well.
}
______________________________________
From the foregoing it will be appreciated that, although specific embodiments of the invention have been described herein for purposes of illustration, various modifications may be made without deviating from the spirit and scope of the invention. For example, one skilled in the art would appreciate that the techniques of the present invention can be used to interface with programs developed in any programming language that conforms with COM. Moreover, the techniques may be generally applicable to the marshaling of parameters between programs developed in various programming languages. Accordingly, the invention is not limited except as by the appended claims.
|
Same subclass Same class Consider this |
||||||||||
