【问题标题】:How to pass array from Cobol to C# COM object如何将数组从 Cobol 传递给 C# COM 对象
【发布时间】:2019-05-17 00:13:53
【问题描述】:

我需要将数组从 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];
        }
    }
}

【问题讨论】:

  • 但这是关于 Visual Cobol 的,我在 Native Cobol 中
  • 很难想象这很重要。请尝试创建一个字符串数组而不是 pic,如 wiki 文章中所示。您可能需要将参数声明为 Array 而不是 string[],这在数组的下限不是 0 时是必需的。

标签: c# com cobol


【解决方案1】:

如果您检查已注册 C# 类的类型库,您会看到它需要一个 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.

【讨论】:

  • 太好了,非常感谢。它现在正在工作。请再问一个问题。如果 COM 对象的返回值是数组,如何管理?我想,我必须再次回到安全阵列。以及如何将这个安全数组中的值移动到标准 Cobol 数组中?
  • 那是正确的指定一个对象引用来返回。这部分文档解释了 safearrays https://supportline.microfocus.com/documentation/books/nx51ws01/dmolda.htm#u023 的使用。如果您可以将客户端移动到托管代码,那么一切都会简单得多。
  • 感谢您的链接。现在我有工作示例传递 int 或字符串的一维数组。但我无法获得二维数组的工作示例。我希望我在 Cobol 中正确创建它,但是当传递给 C# 时,我收到消息“参数不正确”。
  • 这只是表明参数不正确。我已经扩展了 c# 和 cobol 代码以显示一个二维数组正在编组。把代码放到GitHub@(github.com/anok4u2/COBOLCOMStringArrays)。
  • 我还有一个问题。如何将二维数组返回给 Cobol。或者正确的是如何将 safearray 传递给标准 Cobol 变量?
猜你喜欢
  • 2018-07-29
  • 2012-08-21
  • 1970-01-01
  • 2016-07-29
  • 1970-01-01
  • 2022-01-26
  • 1970-01-01
  • 2016-06-26
相关资源
最近更新 更多