HOW TO: Implement .NET COM Interfaces that Require ByRef Parameters (325742)



The information in this article applies to:

  • Microsoft Visual J# .NET 2002

This article was previously published under Q325742

SUMMARY

This step-by-step article describes how to implement a Microsoft .NET COM interface with methods that take parameters by reference in Visual J# .NET. A Java language dictum prevents direct implementation of such methods, so you must manually edit the Microsoft intermediate language (MSIL) code.

back to the top

View the COM Interface in MSIL

Consider the following interface definitions in Interface Definition Language (IDL):
import "oaidl.idl";
import "ocidl.idl";

[
	object,
	uuid(8BDC1D4F-94B3-4a99-AE01-2B40B5A5DA67)
] 
interface IMyInterface : IDispatch {
	HRESULT ShowFace();
};

[
	object,
	uuid(26994F59-B3C3-4681-97D4-583EF892F46A)
] 
interface RefInterface : IDispatch {
	HRESULT RefMethod([in, out] int *num);
	HRESULT MarshalInterfaceToCOM([in] IMyInterface *pI);
};

[
	uuid(09BC59B9-7C65-4B85-8073-42F404EEA3CA)
] 
library ByRefLib {
	interface RefInterface;
	interface IMyInterface;
};
				
To view the intermediate language for this COM type description, compile to a COM type library and convert it to MSIL wrappers by using the TlbImp.exe tool. The following is a sample batch file that uses these COM type definitions. The last line opens a text file of MSIL instructions and metadata for the COM interface .NET wrappers.
midl /client none /server none ByRefLib.idl
del *.c *.h
tlbimp ByRefLib.tlb /namespace:Interop.ByRefLib
ildasm ByRefLib.dll /out=tmp.il
notepad tmp.il
				
The following is a sample of the MSIL code that represents the method declaration:
.method public hidebysig newslot virtual abstract 
    instance void  RefMethod([in][out] int32& num) runtime managed internalcall
				
back to the top

Change the MSIL Method Declaration

In Notepad or a similar text editor, open the output file from the ildasm command (tmp.il in this example), and then find the RefMethod signature declaration line in the class member declarations section. It will look similar to the following:
instance void  RefMethod([in][out] int32& num) runtime managed internalcall
				
This is the line that you must change to enable implementation of the interface in the Java language on .NET. Edit this line so that it matches the following:
instance void  RefMethod([in][out] int32[] marshal([]) num) cil managed 
				
back to the top

Reassemble, Implement, and Compile the Interface

Now you are ready to reassemble the modified MSIL code so that you have a compatible wrapper class to use in a Visual J# .NET implementation. To do this, use the Ilasm.exe tool. The following sample batch completes the reassembly, build, and registration steps to create a sample Java language implementation of these COM interfaces.
sn -k devkey.snk
ilasm /dll /output=ByRefLib.dll /key=devkey.snk tmp.il
vjc Class1.jsl /r:mscorlib.dll /r:ByRefLib.dll /t:library /out:ComImpl.dll
regasm ComImpl.dll /codebase /registered
				
//Class1.jsl

import System.Runtime.InteropServices.*;
import System.Reflection.*;

/** @assembly AssemblyKeyFile("devkey.snk")
 */ 
/** @attribute ClassInterface(ClassInterfaceType.None)
 */ 
/** @attribute GuidAttribute("AFF464D1-7CD5-42b6-8AC6-3F8C292817C3")
 */ 

public class COMImpl 
  implements 
  Interop.ByRefLib.RefInterface, 
  Interop.ByRefLib.IMyInterface
{
  public void RefMethod(int[] num)
  {
    num[0] = (-1)*num[0];
  }

  public void MarshalInterfaceToCOM(
    Interop.ByRefLib.IMyInterface pI)
  {
    pI.ShowFace();
  }

  public void ShowFace()
  {
    com.ms.win32.User32.MessageBox(
      0, 
      this.GetType().ToString(), 
      "ShowFace", 
      0);
  }
}
				
back to the top

Notes About Registration

Notice the /registered switch on the Regasm tool. With Regasm, you register managed implementations for exposure to COM. Errors occur if you try to register managed types that wrap COM types, as in this scenario. In other words, you cannot use Regasm to register TlbImp-generated .NET wrappers. However, in this case, you must register the CoClass for your implementation. To avoid the errors from the COM definitions that you import in this example, use the /registered switch.

Also notice the reference to the Devkey.snk file. This is a temporary key pair that is used to sign the assembly. Although it is not required, it is generally assumed that managed COM implementations are eventually destined for the global assembly cache, which requires a strong name. Signing the assembly in this way gives the assembly a strong name, which can also help you to avoid signing-related error messages.

back to the top

Troubleshooting

If you try to implement a TlbImp-generated wrapper interface that includes ByRef parameters without the workaround that is discussed in this article, you may receive the following error message in the compiler:
Class1.jsl(11,8): error VJS1169: 'COMImpl' must be declared abstract or 'Interop.ByRefLib.RefInterface.RefMethod(byref int)' must be implemented.
The following sample Microsoft Visual Basic 6.0 client code shows an integer value that has been changed by the server.
Private Sub Command1_Click()

   Dim iface1 As RefInterface
   Set iface1 = CreateObject("COMImpl")

   Dim var1 As Long
   Let var1 = 1
   iface1.RefMethod var1
   MsgBox var1

   iface1.MarshalInterfaceToCOM iface1

End Sub
				
back to the top

Modification Type:MinorLast Reviewed:8/15/2005
Keywords:kbhowto kbHOWTOmaster KB325742 kbAudDeveloper