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