Reputation: 349
I need to pass array from MicroFocus Cobol to C# COM object. When I am passing only 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.
**
Cobol code:
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# 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];
}
}
}
Upvotes: 2
Views: 473
Reputation: 56
If you check out the typelib for the registered C# class you will see that it expects a SafeArray of type BSTR(string):
]
interface IAccountNumbers : IDispatch {
[id(0x00000001)]
HRESULT CheckAccount(
[in] SAFEARRAY(BSTR) accounts,
[out, retval] BSTR* pRetVal);
};
Micro Focus COBOL (Net Express and Visual COBOL) support safe arrays so you can use code such as:
$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.
Upvotes: 3