This sample is located in \Samples\Com\CustomMarshal\Plotter.
Note To use this sample, it is recommended that you have Microsoft® Visual C++® version 5.0 or higher installed.
Description
Using the Sample
Technologies Demonstrated
This sample shows how to marshal a simple structure type between a COM type library and Java.
Note You can compile this sample with both Microsoft® Visual C++® 5.0 and Microsoft® Visual C++ 6.0.
To compile the sample
Use Nmake.exe to compile the makefile in the \Samples\Com\CustomMarshal\plotter directory. Type the following command:
Nmake
To run the sample
Run Go.bat from the \Samples\Com\CustomMarshal\prundir directory.
The following example uses a simple COM library, represented by a pseudo-ODL (Object Description Language) file.
typedef struct POINT { long x; long y; } POINT; interface IPlotter : IUnknown { HRESULT DrawLine([in] POINT *start, [in] POINT *end); } coclass CPlotter { [default] interface IPlotter; }
To implement or access this library with Java
Plotter.jnf
[Custom] POINT = java.awt.Point, PointMarshaler
This declaration instructs jactivex to substitute the Java type java.awt.Point when it encounters a reference to the type named POINT in the type library. It also tells the Microsoft virtual machine (Microsoft VM) to use the PointMarshaler class as the hook class for the POINT type.
Important The .idl and .odl files differ on how they expose the type name as shown in the following type definition:
typedef struct _MyStruct { ... } MyStruct;
If you are writing an .idl file, put the structure tag name (_MyStruct) in the .jnf; if writing an .odl file, put the type definition name (MyStruct) in the .jnf.
jactivex /javatlb /n plotter.jnf plotter.tlb
(For jactivex—like its predecessor javatlb—the default output directory is in your TrustLib directory. Use the /d switch to specify a base directory.)
Note By default, jvc disables the @com and @dll directives. To enable these, use the jvc /x- option.
Jactivex creates two .java files that include special @com javadoc syntax. This syntax is required for the jvc compiler to generate the extra bits needed by the Microsoft VM to treat these files as Java/COM classes. For example, the name of the PointMarshaler class is part of these bits.
For this example, jactivex generates two files: CPlotter.java (representing the coclass), and IPlotter.java (representing the interface). These two files are in the %SDKDIR%\Samples\Custdoc\prundir.
Excluding the @com javadoc syntax emitted by jactivex and used by the jvc compiler, the generated source for IPlotter.java looks like the following:
// In the actual file, you will see extra syntax that // represents the extra bits needed for the Microsoft VM // Java/COM marshaling layer. interface IPlotter { public DrawLine(java.awt.Point start, java.awt.Point end); }
IPlotter plotter = (IPlotter)(new CPlotter()); plotter.DrawLine(new Point(x1,y1), new Point(x2,y2));
A Java class can also implement the Plotter library by using IPlotter as shown in the following example:
class MyPlotterImp implements IPlotter { void DrawLine(Point start, Point end) { ... } }
The Microsoft VM marshals the call from Java to Plotter by using the IPlotter.class. It has special bits associated with the start and end parameters that indicate they are a user-defined class and the hook class is PointMarshaler.class. These bits are all generated by jactivex.
When a Java application invokes the DrawLine method, the Microsoft VM loads the PointMarshaler class (if it hasn't already). It then looks for a public static field named cbByValSize. Its presence indicates that the COM type is fixed size. In the previous example, PointMarshaler exposes this field. It is equal to 8, the size (in bytes) of a POINT structure.
The Microsoft VM, therefore, allocates 8 bytes on the stack. The Microsoft VM also invokes another public static method on PointMarshaler called copyToExternal. The Microsoft VM passes copyToExternal a pointer to this 8-byte space and a reference to the end parameter, java.awt.Point. Be aware that the pointer to the 8-byte space is passed as an integer value.
With this information, copyToExternal translates java.awt.Point to a POINT structure in that 8-byte space. The same routine is repeated for the end argument. The COM DrawLine method ultimately receives a pointer to the two stack buffers as its start and end parameters. Because both parameters were marked [in], there is no further action for this simple type.
Note The previous explanation was simplified for brevity. Much of the hook class analysis implied here is done prior to any method calls and does not actually occur at method call time.