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

Reply via email to