I have been hacking away at this for a couple of days. I am definitely getting
punchy. Let me see if I can answer all of your questions:
The COM interface is provided by AcuCobol. That is the interface that I
included in my email. That is a given.
The relevant parts of the COBOL code look like this:
WORKING-STORAGE SECTION. 01 WS-COUNT PIC 9999.
01 WS-STRING-PARM PIC X(200)
OCCURS 3 TIMES. 01 WS-INDEX PIC 9999.
LINKAGE SECTION.
01 VARIANT-COUNT USAGE HANDLE. 01 VARIANT-ARRAY
USAGE HANDLE OCCURS 3 TIMES.
PROCEDURE DIVISION USING VARIANT-COUNT, VARIANT-ARRAY.
MAIN-LINE-SECTION SECTION. MAIN-LINE. CALL "C$GETVARIANT"
USING VARIANT-COUNT WS-COUNT.
IF WS-COUNT > 3 MOVE 3 TO
WS-COUNT END-IF.
PERFORM VARYING WS-INDEX FROM 1 BY 1 UNTIL WS-INDEX >
WS-COUNT CALL "C$GETVARIANT" USING
VARIANT-ARRAY(WS-INDEX) WS-STRING-PARM(WS-INDEX)
END-CALL END-PERFORM. GOBACK.
.
The COBOL program fails on the PERFORM statement. If it is omitted or by
passed, there is no error. The error message is “Passed USING item (#2)
smaller than corresponding LINKAGE item".
Here is the code that I have tried. Pay particular attention to the logic
inside of the switch statement. Those are the approaches that I have taken.
object[] acuArgs = new object[14];
acuArgs[0] = 3;
string[] strings = new string[3];
Array tempStrings;
int whichCase = 4; // 1, 2, 3, or 4
switch (whichCase)
{
case 1:
strings[0] = "S00";
strings[1] = "S01";
strings[2] = "S02";
acuArgs[1] = strings;
break;
case 2:
strings[0] = "S00";
strings[1] = "S01";
strings[2] = "S02";
tempStrings = strings;
acuArgs[1] = tempStrings;
break;
case 3:
strings = new string[] {"S00", "S01", "S02"};
acuArgs[1] = strings;
break;
case 4:
tempStrings = Array.CreateInstance(typeof(string), 3);
tempStrings.SetValue("S00", 0);
tempStrings.SetValue("S01", 0);
tempStrings.SetValue("S02", 0);
acuArgs[1] = tempStrings;
break;
}
acuArgs[2] = null;
acuArgs[3] = null;
acuArgs[4] = null;
acuArgs[5] = null;
acuArgs[6] = null;
acuArgs[7] = null;
acuArgs[8] = null;
acuArgs[9] = null;
acuArgs[10] = null;
acuArgs[11] = null;
acuArgs[13] = null;
object programPath
=
"C:\\ProjectStuff\\WashCIS\\Programs\\InterfaceTest\\SimpleArray\\Array_COM.acu";
object init = null;
AcuGTObjects.AcuGTClass AcugtInterface = null;
try
{
AcugtInterface = new AcuGTObjects.AcuGTClass();
AcugtInterface.Initialize(ref init);
AcugtInterface.Call(ref programPath,
ref acuArgs[0],
ref acuArgs[1],
ref acuArgs[2],
ref acuArgs[3],
ref acuArgs[4],
ref acuArgs[5],
ref acuArgs[6],
ref acuArgs[7],
ref acuArgs[8],
ref acuArgs[9],
ref acuArgs[10],
ref acuArgs[11],
ref acuArgs[12],
ref acuArgs[13]);
}
catch
{
}
finally
{
if (AcugtInterface != null)
{
AcugtInterface.Shutdown();
Marshal.ReleaseComObject(AcugtInterface);
}
}
I hope all of this helps.
Jon
> Date: Thu, 11 May 2006 17:17:28 -0400> From: [EMAIL PROTECTED]> Subject: Re:
> [ADVANCED-DOTNET] how can I pass an array as a safearray through interop that
> expects an variant> To: [email protected]> > I don't think
> you've been clear about exactly what you've tried that caused that "too few
> elements" error. Nothing in your msg has told anything how many elements
> there should be in an array, so that's an odd error message to be getting
> unless you left something out. (If you had Cobol code that expects an array
> of [say] 20 values, and the code failed when accessing the 2nd value, that
> might mean that the whole array wasn't passed over. Can you tell what line
> of Cobol code has failed when there's an error on the Cobol side?)> > If
> you're trying to call a test routine akin to your "intermediate AcuCobol
> adapter program" (IAAP), how did you define it? (It wasn't the Call method
> whose defn you showed, was it? You hadn't mentioned the adapter program yet
> so I didn't think so; and why would you set it up to take 14 parameters? I
> assume that's the AcuCobol COM thingy that lets you call arbitrary Cobol
> routines, and you'll have to pass the name of your IAAP when you call it.)> >
> You hopefully can tell COM that the value to be passed is a safearray; if you
> don't, you have some futzing to do -- on the .Net side, you'll have to stuff
> the array you want to pass into an Object (the .Net "wrapper" type that
> somewhat corresponds to a COM VARIANT), and on the Cobol side, you'll have to
> extract the safearray from the VARIANT* wrapper that surrounds it.> > How are
> you calling the method from .Net? How are you pulling the array elements out
> on the Cobol side? (Any code at all might help -- particularly if you know
> what line caused the error on the Cobol side.)> > Good luck...> > At 04:48 PM
> 5/11/2006, Jon Stonecash wrote (in part)> >I have a need for .NET code to
> call AcuCobol programs. AcuCobol provides a COM interface with a number of
> methods. To the extent that I have tested this interface everything works.>
> >> >The problem is that this interface has a limitation (50) on the number of
> distinct parameters that can be passed from .NET to an individual AcuCobol
> program. I need to exceed that limit by at least a factor of three. (This
> is legacy code and as much as I would wish to change it, I cannot.)> >> >This
> is the definition of the specific COM method as displayed by OleView:> >>
> >[id(0x60020009), helpstring("Calls a COBOL program.")]> >HRESULT Call(>
> >[in] VARIANT* Name,> >[in, out, optional] VARIANT* arg0,> >[snip]> >[in,
> out, optional] VARIANT* arg13);> >> >Since each of the variables is a variant
> and a variant can hold an array, my thought was to package all of the
> parameters up into an array in the .NET code and pass the array into an
> intermediate AcuCobol adapter program that would "unpack" the parameters from
> the array and pass them on to the legacy AcuCobol code.> >> >I have put
> together a test cast that does all of this but when I call the COM object to
> fire up the AcuCobol adapter program, I get back an error message from the
> AcuCobol runtime that says that what I passed has too few elements. My guess
> is that the marshalling logic sees the VARIANT* and only marshalls a single
> value.> >> >I am reading Adam Nathan's book on .NET and COM, but there are
> 1500+ pages and my quick scan does not show anything that is on point. Can
> anyone point me to the path that leads to a solution?> >> >Jon Stonecash> > >
> J. Merrill / Analytical Software Corp> > ===================================>
> This list is hosted by DevelopMentor® http://www.develop.com> > View
> archives and manage your subscription(s) at http://discuss.develop.com
===================================
This list is hosted by DevelopMentor® http://www.develop.com
View archives and manage your subscription(s) at http://discuss.develop.com