Calling Visual COBOL .NET classes from Net Express native programs
This demonstration program shows how a Visual COBOL .NET managed class can be called from a Net Express (or Visual COBOL) native program. The technology used is part of the .NET Interop technology and is known as COM Callable Wrapper or CCW.
Basically what happens is that the .NET class is registered as a COM server so that the native COBOL program can call it as such using the COM support available in Net Express. Actually this is not limited to being called by a Net Express application as any COM enabled client can call this server.
The demonstration consists of two parts, a managed Visual COBOL project called VCCOMServer and a native Net Express project called NXCOMClient. Please unzip the attached file VCCOMDemo.zip onto your C:\drive, retaining the folder structure of the zip file.
VCCOMServer: This class becomes a CCW by turning on the option Register for COM Interop which is found at the bottom of the COBOL tab on the Project Properties page. This option causes the compiler to generate all public methods as COM visible methods and to publish the Interface information to the registry so that any COM client can instantiate the class and call it’s methods. Parameters are automatically converted from .NET to COM types and vice versa as required.
Using Visual COBOL 2010 open up the solution C:\VCCOMDemo\VCCOMServer\VCCOMServer\VCCOMServer.sln and on the build menu select Rebuild Solution. This will register VCCOMServer.dll as a COM Server.
NXCOMClient: This program uses the COM support in Net Express to create an instance of the VCCOMServer class and then to call its methods passing various types of parameters depending on the method.
Using Net Express 5.1 open up the project C:\VCCOMDemo\NXCOMClient\NXCOMClient.app and on the Project menu select Rebuild All.
If you wish to see what methods are available and what parameter types they are expecting you can use the Net Express Type Library Assistant. From the Tools menu select Type Library Assistant. Scroll down in the Registered Type Libraries list until you find VCCOMServer and double click it. To generate COBOL source files and copybooks, specify a copyfile name or leave it as the default TypeLib.cpy. Check the boxes for Add file to Project, Generate Interface Classes and Generate Dual Interfaces and then click the Generate button. Right click in the source pool and select add files to project and add ivccomserver.cbl. This file was generated from the Interface definition in VCCOMServer.cbl and will contain all the available method definitions.
Animate the client program in Net Express to step through the available methods. In this demo empty parameters are used in the call and then they are populated in the VCCOMServer and returned to the client. They are then displayed upon return.
Notice that in order to pass a COBOL group item to a .NET class through COM the group item must be defined as a string in the COM interface class. This is because only .NET native types can be used in this manner and a COBOL group item is not a .NET native type. The group itself can be passed in the client program and will automatically be converted to a COM BSTR type. This is received in the .NET program as a string and can then be mapped onto the group using a set statement.
Source code for VCCOMServer:
id division. interface-id. InterfaceDef as "IVCCOMServer". method-id. testVCstring public. local-storage section. procedure division using lnkString as string. end method. method-id testVCint public. local-storage section. procedure division using lnkInt as binary-long. end method. method-id testVCFloat public. local-storage section. procedure division using lnkFloat as float-long. end method. method-id testVCGroup public. local-storage section. procedure division using lnkString as string. end method. end interface InterfaceDef. *** Starts actual Class implementation class-id VCCOMServer.VCCOMServer implements type IVCCOMServer. method-id testVCstring. local-storage section. procedure division using lnkString as string. move "From method testVCstring" to lnkString goback. end method. method-id testVCint public. local-storage section. procedure division using lnkInt as binary-long. move 50 to lnkInt goback. end method. method-id testVCFloat public. local-storage section. procedure division using lnkFloat as float-long. move 123.75 to lnkFloat goback. end method. method-id testVCGroup public. local-storage section. 01 lnkGroup. 05 lnkName pic x(20). 05 lnkCompany pic x(20). 05 lnkInteger pic x(4) comp-5. 05 lnkDecimal pic s9(4)v99. linkage section. procedure division using lnkString as string. move "Chris Glazier" to lnkName move "Micro Focus" to lnkCompany move 20 to lnkInteger move -987.12 to lnkDecimal set lnkString to lnkGroup goback. end method. end class.
Source code for NXCOMClient:
$set ooctrl(+p) id division. program-id. NXCOMClient. class-control. VCCOMServer is class "$OLE$VCCOMServer.VCCOMServer". working-storage section. 01 anInstance object reference. 01 aString pic x(50) value spaces. 01 anInteger pic x(4) comp-5 value 0. 01 aFloat comp-2 value 0. 01 aGroup. 05 CustName pic x(20). 05 CustCompany pic x(20). 05 CustInteger pic x(4) comp-5. 05 CustDecimal pic s9(4)v99. procedure division. invoke VCCOMServer "new" returning anInstance invoke anInstance "testVCstring" using aString display aString invoke anInstance "testVCint" using anInteger display anInteger invoke anInstance "testVCFloat" using aFloat display aFloat invoke anInstance "testVCGroup" using aGroup display CustName display CustCompany display CustInteger display CustDecimal stop run.