Plotter Custom Marshaling Sample

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

Description

This sample shows how to marshal a simple structure type between a COM type library and Java. 

Using the Sample

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

  1. Write a Plotter.idl or Plotter.odl 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 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.

  3. Use the following command to pass the names of the type library file (.tlb) and the Java type library information file (.jnf) file to jactivex:

    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);
      }
    
  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 \Bin directory of this SDK, see the Build.txt file in the %SDKDIR%\Relnotes directory.

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

Technologies Demonstrated

Custom Marshaling

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