IBM i Global

 View Only
Expand all | Collapse all

python iToolKit - How to retrieve a return value from a CL program

  • 1.  python iToolKit - How to retrieve a return value from a CL program

    Posted Mon October 04, 2021 10:57 AM
    Hello,

    I have a python script calling a CL program, GETIPADDR. The CL program is created using CRTBNDCL and expects two parameters:

    JOBNAME - 26 character
    IPV4ADDR - 15 character

    If I run the CL from a 5250 session and in debug mode with:

    CALL PGM(GETIPADDR) PARM('QPADEV000CGROBINSO  123456' ' ')

    I can see that the IPV4ADDR parameter has been populated when I have a breakpoint on the ENDPGM statement.

    When calling the CL using iToolKit I do not see the returned value in the IPV4ADDR field. The iToolKit call to the CL program returns successfully.

    I am using the following:



    from itoolkit import *
    from itoolkit.lib.ilibcall import *

    itool.add(
    iPgm('my_results',' GETIPADDR')
      .addParm(iData('JOBNAME','26a','QPADEV000CGROBINSO  123456'))
      .addParm(iData('IPV4ADDR','15a',' '))
    )

    itool.call(itransport)

    mypgm_results = itool.dict_out('my_results')
    print(mypgm_results)

    if 'success' in mypgm_results:
      print('Success!')
    else:
      print('Errors occurred.')

    print('\n')
    print("Job Name: ", mypgm_results['JOBNAME'])
    print("IP V4 Address: ", mypgm_results['IPV4ADDR'])
    print("Status of the program call: ", mypgm_results['success'])



    I have used the code at this URL as my template Guru: Calling RPG Programs From Python, Part 1 - IT Jungle

    This example uses iToolKit to call an RPG program to return a value and I was hoping it would be the same for CL.

    So, how do I use iToolKit to return a parameter value from a CL program?

    ------------------------------
    Glenn Robinson
    ------------------------------


  • 2.  RE: python iToolKit - How to retrieve a return value from a CL program

    IBM Champion
    Posted Wed October 06, 2021 09:39 AM
    I can see it as a good exercise and something to know, in how to retrieve a variable from a CL program.
    However, if time is of the essence, you could try to get python to execute sql such as
    SELECT V_CLIENT_IP_ADDRESS FROM TABLE(QSYS2.GET_JOB_INFO('310683/ROB/ROBHQ1'));
    https://www.ibm.com/docs/en/i/7.4?topic=services-get-job-info-table-function

    ------------------------------
    Robert Berendt
    ------------------------------



  • 3.  RE: python iToolKit - How to retrieve a return value from a CL program

    Posted Wed October 06, 2021 10:03 AM
    Thanks did this. I did work out that I could use the get job info DB2 function about an hour after I posted this.

    However, I really hate when I don't know how to do something so any info relating  my original question is very welcome.

    Glenn

    ------------------------------
    Glenn Robinson
    ------------------------------



  • 4.  RE: python iToolKit - How to retrieve a return value from a CL program

    IBM Champion
    Posted Wed October 06, 2021 10:11 AM
    Sorry.  I don't know python.  And I applaud your persistence.

    ------------------------------
    Robert Berendt
    ------------------------------



  • 5.  RE: python iToolKit - How to retrieve a return value from a CL program

    Posted Wed October 06, 2021 10:22 AM
    I applaud you're honesty.

    So, can anyone else help with using iToolKit and Python to retrieve a return value from a CL program?

    ------------------------------
    Glenn Robinson
    ------------------------------



  • 6.  RE: python iToolKit - How to retrieve a return value from a CL program

    IBM Champion
    Posted Wed October 06, 2021 02:12 PM
    Another source which may help:  https://lists.midrange.com/mailman/listinfo/midrange-l

    ------------------------------
    Robert Berendt
    ------------------------------



  • 7.  RE: python iToolKit - How to retrieve a return value from a CL program

    Posted Wed October 06, 2021 02:38 PM
    I googled for 'itoolkit python' and found a github repo with examples.

    This one looks promising:

    python-itoolkit/ipgm_zzcall.py at master · IBM/python-itoolkit
    GitHub remove preview
    python-itoolkit/ipgm_zzcall.py at master · IBM/python-itoolkit
    itoolkit is a Python interface to the XMLSERVICE toolkit for the IBM i platform. - python-itoolkit/ipgm_zzcall.py at master · IBM/python-itoolkit
    View this on GitHub >


    ------------------------------
    Wim Jongman
    ------------------------------



  • 8.  RE: python iToolKit - How to retrieve a return value from a CL program

    Posted Wed October 06, 2021 02:49 PM
    Wim,

    Thanks but I've already seen this and many other resources on the web.

    the iToolKit examples returning a parameter all use Python to call RPG. I can't see what difference CL or RPG would make but I just can't get a return parameter from a CL program.

    Glenn

    ------------------------------
    Glenn Robinson
    ------------------------------



  • 9.  RE: python iToolKit - How to retrieve a return value from a CL program

    IBM Champion
    Posted Wed October 06, 2021 02:57 PM
    The difference between CL and RPG could be something esoteric like is the parameter passed by reference or by value.  Does that make sense?  I could look up more details but if that gets you started I have other fish to fry.
    On another note, going back to SQL:  Think of wrapping your programs and making them a table function, stored procedure, or user defined function.  Consider it a part of a modernization/modularization project.
    Then again, it's perfectly understandable to want to get what you're trying to do working.
    Just tossing out ideas.

    ------------------------------
    Robert Berendt
    ------------------------------



  • 10.  RE: python iToolKit - How to retrieve a return value from a CL program

    Posted Wed October 06, 2021 04:36 PM
    That's a good shout about the passing by reference, I'll do some digging. I can't believe, though, that IBM would not provide this capability when there must be very many CL programs that could be modernised using itoolkit as the interface.

    I am definitely going to use the DB2 Service instead of the itoolkit call as you rightly say, this is the modern way to do this.

    Now, must brush up on my SQL Procedure Language 😁.

    ------------------------------
    Glenn Robinson
    ------------------------------



  • 11.  RE: python iToolKit - How to retrieve a return value from a CL program

    Posted Tue October 12, 2021 01:49 PM

    For a *PGM, the parameters are always passed by reference, so I would not expect any difference between calling a CL program or an RPG program.

    Glenn, could we see the code for the RPG program where it shows how it gets its parameters?



    ------------------------------
    Barbara Morris
    ------------------------------



  • 12.  RE: python iToolKit - How to retrieve a return value from a CL program

    IBM Champion
    Posted Thu October 07, 2021 02:06 AM
    Hi Glenn.

    Can you post the CL program for us to see the code in this?

    I'm asking because to my knowledge there is no difference in how RPG and CL handle their parameters - both receive a pointer for each parameter.
    And I have been caught myself numerous times having a CL program which did not return any value in a parameter - just to realize that I had forgotten to include the CL variable in the PGM parameters! :-D

    Best regards,
    Christian

    ------------------------------
    Christian Jorgensen | IT System Administrator
    Network of Music Partners A/S
    ------------------------------



  • 13.  RE: python iToolKit - How to retrieve a return value from a CL program

    Posted Thu October 07, 2021 06:00 AM
      |   view attached
    Christian,

    Thanks a lot. CL source uploaded.

    ------------------------------
    Glenn Robinson
    ------------------------------

    Attachment(s)

    txt
    getjobip.cll.txt   6 KB 1 version


  • 14.  RE: python iToolKit - How to retrieve a return value from a CL program

    Posted Thu October 07, 2021 11:41 AM
    Edited by Kevin Adler Thu October 07, 2021 11:59 AM
    Hi Glenn, I'm unable to recreate your problem.

    I created a simple CL program:

    /* Dummy GETIPADDR for testing ibm community issue */
    PGM PARM(&JOBNAME &IPV4ADDR)

    DCL VAR(&JOBNAME) TYPE(*CHAR) LEN(26)
    DCL VAR(&IPV4ADDR) TYPE(*CHAR) LEN(15)

    CHGVAR VAR(&IPV4ADDR) VALUE('9.9.9.9')

    ENDPGM​

    I struggled to get anything to work with your sample above. I kept getting MCH3401 "Cannot resolve object  GETIPADDR" Turns out you have a space in the program name in your example that I missed (though I did notice it in the MCH message and was wondering why the formatting was off!).

    Compare

    iPgm('my_results',' GETIPADDR')​

    vs

    iPgm('my_results','GETIPADDR')


    After that I was able to get your code to run successfully:

    Job Name:  QPADEV000CGROBINSO  123456
    IP V4 Address:  9.9.9.9
    Status of the program call:  +++ success  GETIPADDR


    I noticed you're using iLibCall, which calls directly in to XMLSERVICE through PASE APIs. We ran in to issues with this when we moved to 64-bit and XMLSERVICE needed some PTFs. They are listed in the docs - are you missing them? You could also try one of the other transports instead (DatabaseTransport being the next easiest option).

    Finally, the transport class is deprecated (also iDB2Call and iRestCall) and should use the transports listed here instead, with DirectTransport being the direct replacement for iLibCall.



    ------------------------------
    Kevin Adler
    ------------------------------



  • 15.  RE: python iToolKit - How to retrieve a return value from a CL program

    IBM Champion
    Posted Wed October 13, 2021 11:10 AM
    Glenn. On my system I tried your example.  I changed the libcall transport to instead use the database transport and it worked fine.  

    Maybe an issue with the libcall transport and program call ??

    I changed libcall code:

    from itoolkit import *
    from itoolkit.lib.ilibcall import *

    itransport = iLibCall()
    itool = iToolKit()

    To use database transport:

    from itoolkit import *
    from itoolkit.lib.ilibcall import *
    from itoolkit.transport import DatabaseTransport
    import ibm_db_dbi

    conn = ibm_db_dbi.connect()
    itransport = DatabaseTransport(conn)
    itool = iToolKit()

    Regards,
    Richard Schoen
    Web: http://www.richardschoen.net
    Email: richard@richardschoen.net



    ------------------------------
    Richard Schoen
    ------------------------------