× The internal search function is temporarily non-functional. The current search engine is no longer viable and we are researching alternatives.
As a stop gap measure, we are using Google's custom search engine service.
If you know of an easy to use, open source, search engine ... please contact support@midrange.com.



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...


As an Amazon Associate we earn from qualifying purchases.

This thread ...

Replies:

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

This mailing list archive is Copyright 1997-2024 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 on our policy page. If you have questions about this, please contact [javascript protected email address].

Operating expenses for this site are earned using the Amazon Associate program and Google Adsense.