Highlighted
Absent Member.
Absent Member.
4584 views

calling cobol from .net c#, group parameters

Jump to solution

[Migrated content. Thread originally posted on 19 January 2012]

I wan't to call a cobol program from c# and have two parameters which are defines as group elements.

Is there a way to call the cobol without writing a proxy program which then takes every single item into account?
I just wan't to give the cobol program a byte[] (sbyte[]) or a pointer to that array.

In java this is possible!

0 Likes
1 Solution

Accepted Solutions
Highlighted
Micro Focus Expert
Micro Focus Expert

RE: calling cobol from .net c#, group parameters

Jump to solution
You could use a valuetype/struct and marshall this to/from it to a byte[], this would then feel more natural in the C# side.

For example here are some helper methods that will assist you in doing this:


    public T FromByteArray<T>(byte[] rawValue)
    {
        GCHandle handle = GCHandle.Alloc(rawValue, GCHandleType.Pinned);
        T structure = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
        handle.Free();
        return structure;
    }

    public byte[] ToByteArray(object value, int maxLength)
    {
        int rawsize = Marshal.SizeOf(value);
        byte[] rawdata = new byte[rawsize];
        GCHandle handle = GCHandle.Alloc(rawdata, GCHandleType.Pinned);
        Marshal.StructureToPtr(value, handle.AddrOfPinnedObject(),false);
        handle.Free();

        if (maxLength < rawdata.Length)
        {
            byte[] temp = new byte[maxLength];
            Array.Copy(rawdata, temp, maxLength);
            return temp;
        }
        else
        {
            return rawdata;
        }
    }

View solution in original post

0 Likes
5 Replies
Highlighted
Micro Focus Expert
Micro Focus Expert

RE: calling cobol from .net c#, group parameters

Jump to solution
This can be done in Visual COBOL R4 using the SmartLinkage directive.

Open up the Samples Browser under Start Menu->All Programs->Visual COBOL 2010->Visual COBOL Samples and then select the sample COBOL Book in the left column and C# WinBook in the right column and open this in Visual Studio 2010.

Look at the properties on the LegacyBook project under the COBOL tab.
The following Directives are set:

ilsmartlinkage ilcutprefix(lnk-b-) ilcutprefix(lnk-)

This tells the COBOL compiler to make the COBOL group items in the linkage section available to C# as individual elementary items with a .NET type so that C# can access the individual fields directly.

Please see the documentation for this here:

0 Likes
Highlighted
Micro Focus Expert
Micro Focus Expert

RE: calling cobol from .net c#, group parameters

Jump to solution
This can be done in Visual COBOL R4 using the SmartLinkage directive.

Open up the Samples Browser under Start Menu->All Programs->Visual COBOL 2010->Visual COBOL Samples and then select the sample COBOL Book in the left column and C# WinBook in the right column and open this in Visual Studio 2010.

Look at the properties on the LegacyBook project under the COBOL tab.
The following Directives are set:

ilsmartlinkage ilcutprefix(lnk-b-) ilcutprefix(lnk-)

This tells the COBOL compiler to make the COBOL group items in the linkage section available to C# as individual elementary items with a .NET type so that C# can access the individual fields directly.

Please see the documentation for this here:

0 Likes
Highlighted
Absent Member.
Absent Member.

RE: calling cobol from .net c#, group parameters

Jump to solution
I see.

I do not wan't to assign every single field in the structure.
What I wan't is to assign the level 1 item only as the parameter.

Is there a way to do that or can i wrap a C# byte[] or sbyte[] into a MF Reference?

(In Java with the RuntimeSystem I can put a simple byte[] as parameter.)

0 Likes
Highlighted
Micro Focus Expert
Micro Focus Expert

RE: calling cobol from .net c#, group parameters

Jump to solution
Are you referring to calling a native COBOL .dll from C# or a managed COBOL .dll?
Because you reference that you can do this in Java I will assume that it is referring to C# calling native COBOL.

You can do this using a Platform/Invoke call from C# and passing the group item as a StringBuffer or using a C structure etc.

The following is a simple example of C# calling a function named TESTCALL in a native COBOL .dll named cspinvoke.dll and having COBOL populate the group and return to C# where the fields are displayed.


    {
            StringBuilder sb = new StringBuilder(44);
            NativeCobol.TESTCALL(sb);
            txtName.Text = sb.ToString().Substring(0, 20);
            txtCompany.Text = sb.ToString().Substring(20, 20);
            txtAmount.Text =  sb.ToString().Substring(40, 4);
        }
    }
    public class NativeCobol
    {
        [DllImport("cspinvoke.dll", CharSet = CharSet.Ansi, CallingConvention=CallingConvention.Cdecl)]
        public static extern void TESTCALL(StringBuilder cobparams);
    }


and the called COBOL:


       identification division.
       program-id. TESTCALL.
       data division.
       working-storage section.
       linkage section.
       01 group-item.
          05 g-name    pic x(20).
          05 g-company pic x(20).
          05 g-amount  pic 9(4).
       procedure division using group-item.

           move "C. Glazier" to g-name
           move "Micro Focus" to g-company
           move 1234 to g-amount
           goback.

0 Likes
Highlighted
Micro Focus Expert
Micro Focus Expert

RE: calling cobol from .net c#, group parameters

Jump to solution
You could use a valuetype/struct and marshall this to/from it to a byte[], this would then feel more natural in the C# side.

For example here are some helper methods that will assist you in doing this:


    public T FromByteArray<T>(byte[] rawValue)
    {
        GCHandle handle = GCHandle.Alloc(rawValue, GCHandleType.Pinned);
        T structure = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
        handle.Free();
        return structure;
    }

    public byte[] ToByteArray(object value, int maxLength)
    {
        int rawsize = Marshal.SizeOf(value);
        byte[] rawdata = new byte[rawsize];
        GCHandle handle = GCHandle.Alloc(rawdata, GCHandleType.Pinned);
        Marshal.StructureToPtr(value, handle.AddrOfPinnedObject(),false);
        handle.Free();

        if (maxLength < rawdata.Length)
        {
            byte[] temp = new byte[maxLength];
            Array.Copy(rawdata, temp, maxLength);
            return temp;
        }
        else
        {
            return rawdata;
        }
    }

View solution in original post

0 Likes
The opinions expressed above are the personal opinions of the authors, not of Micro Focus. By using this site, you accept the Terms of Use and Rules of Participation. Certain versions of content ("Material") accessible here may contain branding from Hewlett-Packard Company (now HP Inc.) and Hewlett Packard Enterprise Company. As of September 1, 2017, the Material is now offered by Micro Focus, a separately owned and operated company. Any reference to the HP and Hewlett Packard Enterprise/HPE marks is historical in nature, and the HP and Hewlett Packard Enterprise/HPE marks are the property of their respective owners.