ibm-information-center/dist/eclipse/plugins/i5OS.ic.rzalf_5.4.0.1/rzalfileproccallsexamp2.htm

365 lines
16 KiB
HTML
Raw Permalink Normal View History

2024-04-02 14:02:31 +00:00
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html lang="en-us" xml:lang="en-us">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="security" content="public" />
<meta name="Robots" content="index,follow" />
<meta http-equiv="PICS-Label" content='(PICS-1.1 "http://www.icra.org/ratingsv02.html" l gen true r (cz 1 lz 1 nz 1 oz 1 vz 1) "http://www.rsac.org/ratingsv01.html" l gen true r (n 0 s 0 v 0 l 0) "http://www.classify.org/safesurf/" l gen true r (SS~~000 1))' />
<meta name="DC.Type" content="reference" />
<meta name="DC.Title" content="Example 2: An i5/OS ILE program that uses pointer arguments in a call to an i5/OS PASE procedure" />
<meta name="abstract" content="In this example, an i5/OS ILE program uses two different techniques to allocate and share memory storage with the i5/OS PASE procedure that it calls." />
<meta name="description" content="In this example, an i5/OS ILE program uses two different techniques to allocate and share memory storage with the i5/OS PASE procedure that it calls." />
<meta name="DC.Relation" scheme="URI" content="rzalfileproccalls.htm" />
<meta name="copyright" content="(C) Copyright IBM Corporation 2000, 2006" />
<meta name="DC.Rights.Owner" content="(C) Copyright IBM Corporation 2000, 2006" />
<meta name="DC.Format" content="XHTML" />
<meta name="DC.Identifier" content="rzalfileproccallsexamp2" />
<meta name="DC.Language" content="en-us" />
<!-- All rights reserved. Licensed Materials Property of IBM -->
<!-- US Government Users Restricted Rights -->
<!-- Use, duplication or disclosure restricted by -->
<!-- GSA ADP Schedule Contract with IBM Corp. -->
<link rel="stylesheet" type="text/css" href="./ibmdita.css" />
<link rel="stylesheet" type="text/css" href="./ic.css" />
<title>Example 2: An i5/OS ILE program that uses pointer arguments in a
call to an i5/OS PASE
procedure</title>
</head>
<body id="rzalfileproccallsexamp2"><a name="rzalfileproccallsexamp2"><!-- --></a>
<!-- Java sync-link --><script language="Javascript" src="../rzahg/synch.js" type="text/javascript"></script>
<h1 class="topictitle1">Example 2: An i5/OS ILE program that uses pointer arguments in a
call to an i5/OS PASE
procedure</h1>
<div><p>In this example, an <span class="keyword">i5/OS™</span> ILE
program uses two different techniques to allocate and share memory storage
with the <span class="keyword">i5/OS</span> PASE procedure
that it calls.</p>
<div class="example"><img src="./delta.gif" alt="Start of change" /><div class="note"><span class="notetitle">Note:</span> By using the following code examples, you
agree to the terms of the <a href="codedisclaimer.htm">Code license and disclaimer information</a>.</div>
<pre>/* Name: ileMain.c
*
* Call an i5/OS PASE procedure from ILE
*
* This example uses the Qp2dlopen, Qp2dlsym, and Qp2CallPase2 ILE
* functions to call an i5/OS PASE function passing in parameters
*
* Compile like so:
*
* CRTBNDC PGM(mylib/ilemain)
* SRCFILE(mylib/mysrcpf)
* TERASPACE(*YES *TSIFC)
*/
#include &lt;stdio.h&gt;
#include &lt;stddef.h&gt;
#include &lt;errno.h&gt;
#include &lt;qp2user.h&gt;
/* Use EBCDIC default job CCSID in Qp2dlopen and Qp2dlsym calls */
#define JOB_CCSID 0
/* start i5/OS PASE in this process */
void startPASE(void) {
/* start64 starts the 64 bit version of i5/OS PASE */
char *start64Path="/usr/lib/start64";
char *arg_list[2];
arg_list[0] = start64Path;
arg_list[1] = NULL;
Qp2RunPase(start64Path,
NULL,
NULL,
0,
819,
(char**)&amp;arg_list,
NULL);
}
/* open a shared library */
QP2_ptr64_t openlib(char * libname) {
QP2_ptr64_t id;
int * paseErrno;
/* Qp2dlopen dynamically loads the specified library returning an
* id value that can be used in calls to Qp2dlsym and Qp2dlcose */
id = Qp2dlopen(libname,
(QP2_RTLD_NOW |
QP2_RTLD_MEMBER ),
JOB_CCSID);
if (id == 0) {
printf("Qp2dlopen failed. ILE errno=%i\n", errno);
if ((paseErrno=Qp2errnop()) != NULL)
printf("Qp2dlopen failed. i5/OS PASE errno=%i\n", *paseErrno);
printf("Qp2dlopen failed. Qp2dlerror = %s\n", Qp2dlerror());
}
return(id);
}
/* find an exported symbol */
void * findsym(const QP2_ptr64_t id, const char * functionname) {
void * symbol;
int * paseErrno;
/* Qp2dlsym locates the function descriptor for the
* specified function */
symbol = Qp2dlsym(id, functionname, JOB_CCSID, NULL);
if (symbol == NULL) {
printf("Qp2dlsym failed. ILE errno = %i\n", errno);
if ((paseErrno=Qp2errnop()) != NULL)
printf("Qp2dlsym failed. i5/OS PASE errno=%i\n", *paseErrno);
printf("Qp2dlsym failed. Qp2dlerror = %s\n", Qp2dlerror());
}
return(symbol);
}
/* call i5/OS PASE procedure */
int callPASE(const void * functionsymbol,
const void * arglist,
const QP2_arg_type_t * signature,
const QP2_result_type_t result_type,
void * buf,
const short buflen) {
int * paseErrno;
int rc;
/* Call Qp2CallPase2 to run the unction function */
rc = Qp2CallPase2(functionsymbol,
arglist,
signature,
result_type,
buf,
buflen);
if (rc != 0) {
printf("Qp2CallPase failed. rc=%i, ILE errno=%i\n", rc, errno);
if ((paseErrno=Qp2errnop()) != NULL)
printf("Qp2CallPase failed. i5/OS PASE errno=%i\n", *paseErrno);
printf("Qp2CallPase failed. Qp2dlerror=%s\n", Qp2dlerror());
}
}
int main(int argc, char *argv[])
{
/* we will call a function in i5/OS PASE named "paseFunction"
* the prototype for the function looks like this:
* int paseFunction(void * input, void * output ) */
/* "signature" is the argument signature for the PASE routine "paseFunction" */
const QP2_arg_type_t signature[] = {QP2_ARG_PTR64, QP2_ARG_PTR64, QP2_ARG_END};
/* "paseFunctionArglist" are the arguments for the PASE routine "paseFunction" */
struct {
QP2_ptr64_t inputPasePtr;
QP2_ptr64_t outputPasePtr;
} paseFunctionArglist;
/* "inputString" will be one of the arguments to the PASE routine
* "paseFunction" we will call
* This is the string "input" in ASCII */
const char inputString[] = {0x69, 0x6e, 0x70, 0x75, 0x74, 0x00};
/* "outputILEPtr" will be a pointer to storage malloc'd from PASE heap */
char * outputILEPtr;
/* "id" is the identifier for the library opened by Qp2dlopen */
QP2_ptr64_t id;
/* "paseFunction_ptr" is the pointer to the routine "paseFunction" in PASE */
void * paseFunction_ptr;
/* "inputAndResultBuffer" is the buffer of storage shared between ILE and PASE
* by Qp2CallPase2. This buffer contains space for the PASE function result */
struct {
QP2_dword_t result;
char inputValue[6];
} inputAndResultBuffer;
int rc;
int * paseErrno;
/* start i5/OS PASE in this process */
startPASE();
id = openlib("/home/joeuser/libpasefn.a(shr64.o)");
if (id !=0) {
/* Locate the symbol for "paseFunction" */
paseFunction_ptr = findsym(id, "paseFunction");
if (paseFunction_ptr != NULL) {
/* set input arguments for the call to paseFunction() */
/* copy the inputString into the inputAndResultBuffer */
strcpy(inputAndResultBuffer.inputValue, inputString);
/* by setting inputPasePtr argument to the offset of the
* inputValue by-address argument data in the
* inputAndResultbuffer structure and OR'ing that with
* QP2_ARG_PTR_TOSTACK QP2CallPase2 will "fixup" the
* actual argument pointer passed to the PASE function
* to point to the address (plus the offset) of the
* copy of the inputAndResultbuffer that Qp2CallPase2
* copies to i5/OS PASE storage */
paseFunctionArglist.inputPasePtr =
(QP2_ptr64_t)((offsetof(inputAndResultBuffer, inputValue))
| QP2_ARG_PTR_TOSTACK);
/* allocate memory from the i5/OS PASE heap for an output
* argument. Qp2malloc will also set the i5/OS PASE address
* of the allocated storage in the outputPasePtr
* argument */
outputILEPtr = Qp2malloc(10, &amp;(paseFunctionArglist.outputPasePtr));
/* Call the function in i5/OS PASE */
rc = callPASE(paseFunction_ptr,
&amp;paseFunctionArglist,
signature,
QP2_RESULT_DWORD,
&amp;inputAndResultBuffer,
sizeof(inputAndResultBuffer));
if (rc != 0) {
printf("output from paseFunction = &gt;%s&lt;\n",
(char*)outputILEPtr);
printf("return code from paseFunction = %d\n",
(int)inputAndResultBuffer.result);
} /* rc != 0 */
} /* paseFunction_ptr != NULL */
} /* id != 0 */
/* Close the Qp2dlopen instance, and then call Qp2EndPase
* to end i5/OS PASE in this job */
Qp2dlclose(id);
Qp2EndPase();
return 0;
}
Source code for the i5/OS Procedure paseFunction that is called by the ileMain.c program:
/* i5/OS PASE function to be called from ILE
*
* Compile with something like:
* xlc -q64 -c -o paseFunction.o paseFunction.c
* ld -b64 -o shr64.o -bnoentry -bexpall -bM:SRE -lc paseFunction.o
* ar -X64 -r /home/joeuser/libpasefn.a shr64.o
*
* The ILE side of this example expects to find libpasefn.a in
* /home/joeuser/libpasefn.a
*
* The compiler options -qalign=natural and -qldbl128 are
* necessary only when interacting with i5/OS ILE programs
* to force relative 16-byte alignment of type long double
* (used inside type ILEpointer)
*/
#include &lt;stdlib.h&gt;
#include &lt;stdio.h&gt;
int paseFunction(void * inputPtr, void * outputPtr)
{
/* An output string to return from i5/OS PASE to ILE *
* this is the string "output" in EBCDIC */
const char outputValue[] = {0x96, 0xa4, 0xa3, 0x97, 0xa4, 0xa3, 0x00};
printf("Entered paseFunction The input is &gt;%s&lt;\n",
(char*)inputPtr);
/* copy the output results to the outputPtr argument */
memcpy(outputPtr, outputValue, sizeof(outputValue));
return(52); /* return something more interesting than 0 */
}</pre>
<img src="./deltaend.gif" alt="End of change" /></div>
<div class="section"><img src="./delta.gif" alt="Start of change" /><h4 class="sectiontitle">Various functions used in the ILE portion
of Example 2</h4><ul><li><strong>The startPASE() function</strong><p>Before i5/OS PASE can be used in a process, it
must be started. This is done automatically by calling an i5/OS PASE application
main entry point using the APIs, for example, QP2SHELL, QP2TERM, or Qp2RunPase.</p>
<p>However,
because this example is calling an i5/OS PASE function exported from a shared
library (not a main entry point), you must manually start i5/OS PASE. Two i5/OS PASE
starter utilities are available for this purpose: /usr/lib/start32 (to start
the 32-bit version of i5/OS PASE) and /usr/lib/start64 (to start the 64-bit
version of i5/OS PASE).</p>
<div class="p">Be
aware that each i5/OS process
can only have a single instance of i5/OS PASE running. The Qp2ptrsize() API
can be used to determine whether i5/OS PASE is already running. <ul><li>Qp2ptrsize() will return <tt class="sysout">0</tt> if i5/OS PASE is
not currently active in the process.</li>
<li>Qp2ptrsize() will return <tt class="sysout">4</tt> if i5/OS PASE is
active in 32-bit mode.</li>
<li>Qp2ptrsize() will return <tt class="sysout">8</tt> if i5/OS PASE is
active in 64-bit mode.</li>
</ul>
</div>
</li>
<li><strong>The openlib() and findsym() functions</strong><p>These functions open the i5/OS shared
library and obtain a pointer to the function you want to call using the Qp2dlopen()
and Qp2dlsym(). These functions are similar to the dlopen() and dlsym() routines
on many platforms.</p>
</li>
<li><strong>Set up arguments for the Qp2CallPase2 call</strong><p>Before calling Qp2CallPase2()
through the callPASE() function, the main() routine sets up the following
variables that define the interface between ILE and the i5/OS PASE function:</p>
<ul><li>The signature-array variable defines the arguments for the i5/OS PASE function.
The elements in the array are typically set using the #define found in the
qsysinc/h.qp2user include file.</li>
<li>The paseFunctionArglist structure contains the ILE variables that the i5/OS PASE
run time will map into the arguments that will be passed to the i5/OS PASE function
when the function is called. The members in paseFunctionArglist correspond
to the signature of the i5/OS PASE function declared in the signature array.</li>
<li>The inputAndResultBuffer structure contains the ILE variables that the i5/OS PASE
run time will use as a sort of shared buffer between ILE and the i5/OS PASE function
when the function is called. <p>The first member of the structure (<dfn class="term">result</dfn> in
this example) will contain the return value from the i5/OS PASE function. This variable must
match the result-type argument provided as the fourth argument in the call
to the Qp2CallPase2 API. Anything after this first element represents storage
that will be copied into the i5/OS PASE environment when the function is called.</p>
<p>In
this example, the inputValue element of the inputAndResultBuffer structure
will contain the by-address argument data that will be pointed at by the first
argument for the i5/OS PASE
function.</p>
</li>
<li>This example uses two different ways of setting pointer arguments for
the i5/OS PASE
function that is being called. <ul><li>The second argument to the function, paseFunctionArglist.outputPasePtr,
is set by calling the Qp2malloc() function. Qp2malloc() allocates memory from
the i5/OS PASE
runtime heap and returns both an ILEpointer and an i5/OS PASE pointer to the allocated storage.</li>
<li>The first argument, paseFunctionArglist.inputPasePtr, is set to the offset
of the inputValue element of the inputAndResultBuffer structure that is connected
with the qp2user.h #define QP2_ARG_PTR_TOSTACK by OR.<p>This tells the i5/OS PASE
run time to modify the actual pointer value provided on the call to the i5/OS PASE
function with the address where the inputAndResultBuffer.inputValue was copied
into i5/OS PASE
memory.</p>
</li>
</ul>
</li>
</ul>
</li>
<li><strong>The callPASE() function</strong><p>This function calls the i5/OS PASE function
using the Qp2CallPase2() API and the arguments set in the main() routine.</p>
</li>
<li><strong>End i5/OS PASE
in the process</strong><p> After the call to the i5/OS PASE function, the Qp2dlclose() API
is called to unload the i5/OS PASE shared library and Qp2EndPase() is called
to end the start64 program called at the beginning of the example.</p>
</li>
</ul>
<img src="./deltaend.gif" alt="End of change" /></div>
</div>
<div>
<div class="familylinks">
<div class="parentlink"><strong>Parent topic:</strong> <a href="rzalfileproccalls.htm" title="You can call the Qp2CallPase() and Qp2CallPase2() ILE procedures from within other ILE procedures to run an i5/OS PASE program in a job where the i5/OS PASE environment is already running.">Call an i5/OS PASE procedure from within i5/OS programs</a></div>
</div>
</div>
</body>
</html>