Highlighted
pavlli Super Contributor.
Super Contributor.
376 views

Pass array from Native Cobol to Csharp COM Object

Jump to solution

I need to pass array from Native Cobol to C# COM object. When I am passing only single string or number it's working. But with array I got error message: **Exception 65537 not trapped by the class oleexceptionmanager. Description: "Server defined OLE exception"
(80070057): The parameter is incorrect.

I think that I must somehow differently declare array in Cobol part?

Cobol code:

$SET DIRECTIVES (SBODBC.DIR) NSYMBOL"NATIONAL"
$set ooctrl(+p)
identification division.
program-id. pokus444.
special-names.
environment-name is environment-name
environment-value is environment-value
decimal-point is comma.
class-control.
ChkAccNum is class "$OLE$CheckAccountNumber.AccountNumbers".
working-storage section.
01 ChkAccNumObj object reference.
01 accA.
05 acc pic x(34) occurs 100.
01 accR pic x(34).
procedure division.
main section.
display "Zacatek programu"
initialize accA accR
move '1234567890' to acc(1)
move '0987654321' to acc(2)
invoke ChkAccNum "new" returning ChkAccNumObj
invoke ChkAccNumObj "CheckAccount" using accA
returning accR
display accR
exit
.

C# code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace CheckAccountNumber
{
    [Guid("A80930D1-080F-4B04-A2C3-B637428556D6")]
    public interface IAccountNumbers
    {
        [DispId(1)]
        string CheckAccount(string[] accounts);
    }

    [Guid("65A771A0-0DDE-440D-9A4F-C71CEAEE3DF6"),
    ClassInterface(ClassInterfaceType.None)]
    public class AccountNumbers : IAccountNumbers
    {
        public AccountNumbers()
        {
        }

        public string CheckAccount(string[] accounts)
        {
            return accounts[1];
        }
    }
}
0 Likes
1 Solution

Accepted Solutions
pavlli Super Contributor.
Super Contributor.

Re: Pass array from Native Cobol to Csharp COM Object

Jump to solution

On StackOverflow I found solution. Cobol program must use save arrays.

C     $SET DIRECTIVES (SBODBC.DIR) NSYMBOL"NATIONAL"
      $set ooctrl(+p)

       identification division.
       program-id. pokus444.

       special-names.
           environment-name  is environment-name
           environment-value is environment-value
           decimal-point is comma.

       class-control.
mftech   CharacterArray is class "chararry"
mftech   OLESafeArray is class "olesafea"
         ChkAccNum is class "$OLE$CheckAccountNumber.AccountNumbers".

       working-storage section.
mftech copy mfole.
mftech copy olesafea.
       01 ChkAccNumObj object reference.
       01 accA.
         05 acc pic x(34) occurs 100.
       01 accR pic x(34).
mftech 01 ws-stringArray               object reference.
mftech 01 ws-vartype                   pic 9(4) comp-5.
mftech 01 ws-dimension                 pic 9(4) comp-5.
mftech 01 ws-saBound                   SAFEARRAYBOUND occurs 1.
mftech 01 ws-iIndex                    pic 9(9) comp-5.
mftech 01 ws-len                       pic 9(9) comp-5.
mftech 01 ws-hresult                   pic 9(9) comp-5.

       procedure division.
       main section.
           display "Zacatek programu"
           initialize accA accR
           move '1234567890' to acc(1)
           move '0987654321' to acc(2)

      ***** Create a 1 Dimension OLESAFEARRAY to pass string array
           move VT-BSTR to ws-vartype
           move 1       to ws-dimension
           move 2 to cElements of ws-saBound(1)
           move 0 to llBound of ws-saBound(1)
           invoke OLESafeArray "new" using by value ws-vartype
                                                    ws-dimension
                                           by reference ws-saBound(1)
               returning ws-stringArray
           end-invoke

      ***** Populate 2 Elements in OLESAFEARRAY
           move 0  to ws-iIndex
           move 10 to ws-len
           invoke ws-stringArray "putString"
                   using by reference ws-iIndex
                         by value     ws-len
                         by reference acc(1)
               returning ws-hresult
           end-invoke
           if ws-hresult not = 0
               display "Die Gracefully"
               stop run
           end-if
           move 1 to ws-iIndex
           move 10 to ws-len
           invoke ws-stringArray "putString"
                   using by reference ws-iIndex
                         by value ws-len
                         by reference acc(2)
               returning ws-hresult
           end-invoke
           if ws-hresult not = 0
               display "Die Gracefully"
               stop run
           end-if


           invoke ChkAccNum "new" returning ChkAccNumObj
           invoke ChkAccNumObj "CheckAccount" using ws-stringArray
            returning accR
           display accR
           exit
           .
0 Likes
5 Replies
pavlli Super Contributor.
Super Contributor.

Re: Pass array from Native Cobol to Csharp COM Object

Jump to solution

On StackOverflow I found solution. Cobol program must use save arrays.

C     $SET DIRECTIVES (SBODBC.DIR) NSYMBOL"NATIONAL"
      $set ooctrl(+p)

       identification division.
       program-id. pokus444.

       special-names.
           environment-name  is environment-name
           environment-value is environment-value
           decimal-point is comma.

       class-control.
mftech   CharacterArray is class "chararry"
mftech   OLESafeArray is class "olesafea"
         ChkAccNum is class "$OLE$CheckAccountNumber.AccountNumbers".

       working-storage section.
mftech copy mfole.
mftech copy olesafea.
       01 ChkAccNumObj object reference.
       01 accA.
         05 acc pic x(34) occurs 100.
       01 accR pic x(34).
mftech 01 ws-stringArray               object reference.
mftech 01 ws-vartype                   pic 9(4) comp-5.
mftech 01 ws-dimension                 pic 9(4) comp-5.
mftech 01 ws-saBound                   SAFEARRAYBOUND occurs 1.
mftech 01 ws-iIndex                    pic 9(9) comp-5.
mftech 01 ws-len                       pic 9(9) comp-5.
mftech 01 ws-hresult                   pic 9(9) comp-5.

       procedure division.
       main section.
           display "Zacatek programu"
           initialize accA accR
           move '1234567890' to acc(1)
           move '0987654321' to acc(2)

      ***** Create a 1 Dimension OLESAFEARRAY to pass string array
           move VT-BSTR to ws-vartype
           move 1       to ws-dimension
           move 2 to cElements of ws-saBound(1)
           move 0 to llBound of ws-saBound(1)
           invoke OLESafeArray "new" using by value ws-vartype
                                                    ws-dimension
                                           by reference ws-saBound(1)
               returning ws-stringArray
           end-invoke

      ***** Populate 2 Elements in OLESAFEARRAY
           move 0  to ws-iIndex
           move 10 to ws-len
           invoke ws-stringArray "putString"
                   using by reference ws-iIndex
                         by value     ws-len
                         by reference acc(1)
               returning ws-hresult
           end-invoke
           if ws-hresult not = 0
               display "Die Gracefully"
               stop run
           end-if
           move 1 to ws-iIndex
           move 10 to ws-len
           invoke ws-stringArray "putString"
                   using by reference ws-iIndex
                         by value ws-len
                         by reference acc(2)
               returning ws-hresult
           end-invoke
           if ws-hresult not = 0
               display "Die Gracefully"
               stop run
           end-if


           invoke ChkAccNum "new" returning ChkAccNumObj
           invoke ChkAccNumObj "CheckAccount" using ws-stringArray
            returning accR
           display accR
           exit
           .
0 Likes
pavlli Super Contributor.
Super Contributor.

Re: Pass array from Native Cobol to Csharp COM Object

Jump to solution

But I have more questions. How to process array when I return it back from COM object - how to move it to standard Cobol array? And how to process 2 dimensional array?

0 Likes
pavlli Super Contributor.
Super Contributor.

Re: Pass array from Native Cobol to Csharp COM Object

Jump to solution

I found this article about multidimensional safearrays, but I am unable to get it working. I mean to pass 2dimensional array to COM object and then return some value back to Cobol

0 Likes
Micro Focus Expert
Micro Focus Expert

Re: Pass array from Native Cobol to Csharp COM Object

Jump to solution

The SafeArray class is documented in the NX documentation here

You can find out information about the array's contents and unpack the array into its various elements using its methods.

It does show example code as well.

This is a somewhat cumbersome approach to interface with C#

Have you looked into the Visual COBOL product at all? Visual COBOL would allow you to create a managed .NET COBOL class wrapper that was registered as COM and you could pass the array parameter directly to the managed COBOL program without using SafeArray. The managed COBOL class could then format the array as a .NET array and pass it onto C# and do the same on the return trip to native COBOL.

Just a thought...

0 Likes
pavlli Super Contributor.
Super Contributor.

Re: Pass array from Native Cobol to Csharp COM Object

Jump to solution

Hi Chris,

thanks for the link. I am already studying it. Now I am able to pass 1dimensional array between Cobol nad C#. But I am still unable to make 2dimensional example working. I suppose that, if 1dimensional working, 2dimensional must working too 🙂

Yes I know Visual Cobol, but product which I am developing forcing me to use Native Cobol and C#

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.