Scott, Simon, thank you both very much for your candid and helpful descriptions. As you say below, this was a proof of concept for me -- I'd heard that RPG could call C functions and I was trying to figure out how one goes about doing that.

The fun began with finding out how to bind it all properly. The fact that I eventually got the RPG to run in the first place was a victory that evoked a happy-dance!

Both explanations do help me with a segue question I was going to ask, which is what is the proper way to pass data structures back and forth between C and RPG. I had a suspicion that struct would come into play, since in my mind as a C programmer, seeing an RPG DS just looks like a struct to me!

Thanks again everyone, I'm going to digest these e-mails further and try some of the suggestions!


Simon Coulter wrote:
On 10/01/2006, at 8:59 AM, Peter Grace wrote:

I think that this has something to do with the pointer that I'm creating
doesn't exist outside of the service program?  Is this correct, or am I
just making a big goof?

Yes to both questions actually. The C function is defined as returning a pointer. This pointer will contain the address of the 25 byte array. However this array is declared in automatic storage so it's gone by the time the pointer is returned. That's problem 1.

Problem 2 is that C expects an int (4 bytes) but the prototype is passing a 2-byte integer. RPG will widen the value because that's what C expects but you shouldn't rely on this behaviour.

Problem 3 is that the C function returns a pointer but the RPG prototype says it returns a 25 byte variable. Not the same thing at all.

The correct prototype for the function is:
        D getStr          PR              *   extproc('getStr')
        D                               10I 0 VALUE

But that only makes them map correctly. It doesn't deal with problem 1.

What is the "Right Way" for me to return a char* array (or even a data
structure) via a bound-C service program to a RPG program?  Is there
even a right way to do it?

"Right" depends on what you're trying to accomplish.

A quick-and-dirty solution to Problem 1 is to make the array static but using static storage is messy and sloppy.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

char* getStr(int incomingVar);

char* getStr(int incomingVar)
   static char foo[25];
   return foo;
} You could also return a structure containing the 25 bytes. This would map better to RPG's view of the world but is likely to give C programmers the squits. They start squawking about "no respect for the stack" and other such nonsense.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

char* getStr(int incomingVar);

char* getStr(int incomingVar)
   struct { char data[25];
          } foo;
   return foo;
} This still requires that RPG knows it is dealing with null-terminated strings. That's not 'normal' but you can treat it as a fixed-length string by doing the work in C to blank out the null byte and ensure the rest of the field is blanks too.

Finally you could use the %STR function in RPG to convert the null-terminated string to something RPG can process as long as the storage referenced by the pointer is still available.
        C                               EVAL            fooStr = %STR(getstr(1))

I presume this code is simply an example because there is no reason to invoke C just to convert a number to a character representation. You do that in RPG in any number of ways.

Simon Coulter.
    FlyByNight Software         AS/400 Technical Specialists
    Phone: +61 3 9419 0175   Mobile: +61 0411 091 400        /"\
    Fax:   +61 3 9419 0175                                   \ /
                  ASCII Ribbon campaign against HTML E-Mail  / \

This thread ...


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

This mailing list archive is Copyright 1997-2019 by 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].