Microsoft SDK for Java

Example of Custom Marshaling

This section shows how to marshal a simple structure type between a COM type library and Java. The following example uses a simple COM library, represented by a pseudo-IDL (Interface 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

  1. Write a plotter.idl file for the COM library and pass it to the mktyplib tool (in Microsoft® Visual C++®) to generate a type library file called plotter.tlb.

  2. Write a .jnf file that describes all the user-defined types. The .jnf file would look like this for the POINT type:

    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 VM to use the PointMarshaler class as the hook class for the POINT type.

           typedef struct _MyStruct
           {
             ...
           } MyStruct;
    
  3. Pass the names of the type library file (.tlb) and the Java type library information file (.jnf) file to jactivex using the following command:
    Jactivex /javatlb /n plotter.jnf plotter.tlb
    

    (For jactivex—like its predecessor javatlb—the default output directory is in your TrustLib directory. You may want to 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). 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);
      }
    
  4. Compile CPlotter.java and IPlotter.java using jvc. You must use jvc version 1.02.3920 or later, which interprets the extra @com syntax that jactivex generates. For the version number of jvc that is included in the \Relnotes directory of this SDK, see build.txt.

  5. A Java application can now load and use an installed Plotter library by invoking the following code:
    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 sample files for this section are in the Microsoft SDK for Java. The sources for the previous example are in %SDKDIR%\Samples\Com\CustomMarshal\plotter. The sources for point are in %SDKDIR%\Samples\Com\CustomMarshal\point. To execute the sample, change the current directory to %SDKDIR%\Samples\Com\CustomMarshal\prundir. Run the Go.bat file. For more information, see the COM Samples Overview. For information about other samples in this SDK, see the Samples Overview.

The Microsoft VM marshals the call from Java to Plotter by using 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.exe.

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

© 1999 Microsoft Corporation. All rights reserved. Terms of use.