Wow!   

-----Original Message-----
From: c400-l-bounces+lim.hock-chai=usamobility.com@xxxxxxxxxxxx
[mailto:c400-l-bounces+lim.hock-chai=usamobility.com@xxxxxxxxxxxx] On
Behalf Of Scott Klement
Sent: Wednesday, November 16, 2005 3:57 PM
To: C programming iSeries / AS400
Subject: Re: [C400-L] prototype in c

Hello,

> anybody know how to prototype the following RPG prototype of a export 
> procedure in c?

Yes, I do. :)


> D $rtvREFERP      pr              n
> D  prefCat                       3    value
> D  prefKey                      27    value
> D  pRefDat                      90    options(*nopass :*varSize)
> D  pRefDatLen                    2  0 value options(*nopass)

This isn't a very C friendly prototype.  Here are a few considerations:

a) prefCat & prefKey are alphanumeric strings, but are passed by value.

That's a somewhat alien concept in C.  You can't usually pass a
character string by value, only reference.  However, there's an easy
workaround... 
if you put the character string in a data structure, you can pass that
data structure by value.  It works.

b) The options(*nopass) parameters should be replaced by ... on a C
prototype.  Unfortunately, that means that the compiler won't check that
you're passing the correct parameter type, you'll have to rely on the
programmer.

b) The return type of N (an RPG indicator) is a 1-character variable.
RPG will pass that as a character string, but C will be looking for a 1
character numeric field.  Somewhere under the covers, they're treated
differently, and this causes problems.

There are two workarounds.  One is to change the RPG prototype to use
ExtProc(*CL).  Unfortunately, that means you have to recompile all
existing programs that call the RPG subprocedure.

The other alternative is to return a 2-character long data structure in
the C program, and then just ignore the 2nd character. This'll cause C
to set up the return type the way the RPG program would.

Note that you'd have this same problem if you called the RPG from a CL
porgram.  That's why the fix is called ExtProc(*CL) from within RPG.  In
my prototype, however, I'll use the C workaround isntead of changing the
RPG because it's less intrusive.

c) In order for %PARMS to work in the RPG subprocedure, you need to pass
at least a minimal operational descriptor.  RPG does this automatically,
as does CL.  But in C to make it do that, you have to force the issue
with a descriptor #pragma.

d) Unless you use ExtProc, an RPG program converts the subprocedure's
name to all-uppercase.  C, on the other hand, keeps things in the same
case that you typed.  So to use the name "$rtvREFERP" in the C program,
you need to use a map #pragma to rename it. (#pragma map is like ExtPRoc
in
RPG)

Taking all of these things into account, here's the prototype that I
came up with:

#include <decimal.h>

typedef struct {
    char value[3];
} prefCat_t;

typedef struct {
    char value[27];
} prefKey_t;

typedef struct {
    char value;
    char reserved;
} prefRtn_t;

#pragma map ($rtvREFERP, "$RTVREFERP")
prefRtn_t $rtvREFERP( prefCat_t prefCat, prefKey_t prefKey, ...);
#pragma descriptor ( void $rtvREFERP(void,void) )


Here's an example of calling the subprocedure from ILE C, with and
without the optional parms:

#include <stdio.h>
#include <string.h>
#include "QCSRC/RTVREFERP"

int main(int argc, char **argv) {

#define DATALEN 90
     prefCat_t cat;
     prefKey_t key;
     prefRtn_t rc;
     char data[DATALEN+1];
     _Decimal(2,0) len;

     /* RPG doesn't like null-terminated strings.  The data for
        each argument goes at the start of the variable, and the
        rest of the variable should be filled with blanks. */

     memset(&cat, ' ', sizeof(key));
     memset(&key, ' ', sizeof(key));

     memcpy(&cat, "AA", 2);
     memcpy(&key, "Whatever goes in prefKey...", 27);


     /* Call RPG subprocedure */

     rc = $rtvREFERP( cat, key );
     printf("rc = %c\n", rc.value);


     /* Call again with optional parms supplied */

     len = DATALEN;
     memset(data, ' ', DATALEN);
     memcpy(data, "Some sort of data", 17);

     rc = $rtvREFERP( cat, key, data, len );

     data[DATALEN] = '\0';
     printf("rc = %c, data = %s \n", rc.value, data);

     return 0;
}


Hope that helps...

--
This is the C programming iSeries / AS400 (C400-L) mailing list To post
a message email: C400-L@xxxxxxxxxxxx To subscribe, unsubscribe, or
change list options,
visit: http://lists.midrange.com/mailman/listinfo/c400-l
or email: C400-L-request@xxxxxxxxxxxx
Before posting, please take a moment to review the archives at
http://archive.midrange.com/c400-l.



This thread ...

Follow-Ups:

Follow On AppleNews
Return to Archive home page | Return to MIDRANGE.COM home page

This mailing list archive is Copyright 1997-2019 by midrange.com and David Gibbs as a compilation work. Use of the archive is restricted to research of a business or technical nature. Any other uses are prohibited. Full details are available here. If you have questions about this, please contact [javascript protected email address].