如何将数组从Cobol传递到C#COM对象

时间:2019-05-16 12:14:24

标签: c# com cobol

我需要将数组从MicroFocus Cobol传递到C#COM对象。当我只传递字符串或数字时,它起作用了。但是用数组我得到了错误信息: **异常65537未被类oleexceptionmanager捕获。 说明:“服务器定义的OLE异常”
(80070057):参数不正确。
** Cobol代码:

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.
     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#代码:

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];
        }
    }
}

1 个答案:

答案 0 :(得分:3)

如果您为注册的C#类签出typelib,您将看到它期望的类型为BSTR(string)的SafeArray:

]
interface IAccountNumbers : IDispatch {
    [id(0x00000001)]
    HRESULT CheckAccount(
                    [in] SAFEARRAY(BSTR) accounts, 
                    [out, retval] BSTR* pRetVal);
};

Micro Focus COBOL(Net Express和Visual COBOL)支持安全数组,因此您可以使用以下代码:

      $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(1)
               returning ws-hresult
           end-invoke
           if ws-hresult not = 0
               display "Die Gracefully"
               stop run
           end-if

           invoke ChkAccNum "new" returning ChkAccNumObj
      ***** Pass across the OLESAFEARRAY
           invoke ChkAccNumObj "CheckAccount" using ws-stringArray
                                          returning accR
           display accR
           stop run.