Midrange News for the IBM i Community


Posted by: Bob Cozzi
Rogue Programmer
Cozzi Productions, Inc.
Chicagoland
Using C C++ from RPG IV
has no ratings.
Published: 13 Jul 2015
Revised: 16 Jul 2015 - 3199 days ago
Last viewed on: 18 Apr 2024 (11903 views) 

Using IBM i? Need to create Excel, CSV, HTML, JSON, PDF, SPOOL reports? Learn more about the fastest and least expensive tool for the job: SQL iQuery.

Calling C Functions Published by: Bob Cozzi on 13 Jul 2015 view comments

I recently spent a year building an SQL Query tool named SQL Query File (see more on this here) and decided to provide some "lessons learned" during that project regarding how to interface non-RPG modules and functions with RPG IV. The entire SQL Query File package is written in C++ with C wrappers that provide RPG interfaces (see this week's blog post below for details). I had to invent some things and leverage some a great features built-into this platform. I have no idea how many entries in this blog will be published, it all depends on whether there is any feedback/interest. So let's get started.

When you're done reading this page, be sure to click the NEXT button (top rightside of page) to read the next installment.

Prototyping a Simple C Function in RPG IV

This blog illustrates how to interface RPG with the C and C++ languages. Technical RPG does not play nice with C++, so any C++ interfaces have to be wrapped in C interfaces before RPG can call them. This first installment illustrates how to call a simple C function using RPG Prototyping. The example function, "Center Text within a Variable". Here's the RPG program for the function we want to call.

     D centerText      PR                  extProc(*CWIDEN:'centerText')    
     D  text                      65535A   OPTIONS(*VARSIZE)                
     D  textLength                   10I 0 Value

As you can see, our CENTERTEXT function accepts 2 required parameters.

  1. The RPG character field whose text shall be centered withing the variable.
  2. The Length of the first parameter.

To call our function from RPG, simply inlude the prototype and evoke it like a function:

centerText( compName : %size(compName) ); 

Of course the prototype alone will not perform the centering task, we need some cod behind it. But first let's review the RPG Prototype:

Line 1 is the prototype name and points to the function (the C function in our example) that is to be called to perform the task. Since we are calling a C function, and that C function using something other than only character parameters, we include the *CWIDEN prefix on the EXTPROC keyword. This fixes any incompatabilities between RPG and C. The C function's name is also specified; it is case-sensitive, hence the quoted name in upper/lower case letters.

Line 2 is the input/output character variable whose text is centered within it. Any size field may be specified. The OPTIONS(*VARSIZE) allows you specify any length field.

Line 3 receives the length of the field whose text is being centered. Basicall this should always be coded as the %SIZE of parameter 1 unless you're doing some other kind of centering and you need to sepecify a specific length. The length is converted by the compiler into a 4-byte integer and passed to our C function.

C Function centerText

Let's take a look at a basic C function that accepts these parameters and performs text centering.

#include 
#include 

using namespace std;
                       
extern "C" void centerText( char* textToCenter, int textLen);

void centerText( char* myText, int textLen)
{
   std::string text;
   if (textLen <= 1)
      return;

   text.assign(myText,textLen);
   trim(text);  // function not shown. More on it next time.
   text = std::string((textLen - text.length()) / 2, ' ') + text;
   memset(myText,' ', textLen);
   memcpy(myText,text.c_str(),text.length());
   return;
}      

This function is actually written with C++, but as I mentioned, RPG does not play nice with C++, so we force the C++ compiler to export the "centerText" function using C notation. This makes it available to RPG IV prototyping.

The C++ language includes an class type of "string" this class allows you to use "fields" in C++ similar to how we use them in RPG. They probably aren't as fast as declaring a fixed length character array, but the benefit is in ease-of-use. So I've decided to use them here.

We declare a local variable named text that is a type(string). The "std::" that prefixes the "string" datatype isn't strictly necessary in this example because we also use the namespace keyword. This basically tells the compiler to look at this collection of classes whenever an unqualified class is specified. So in our example, "std::string" and "string" perform the same task.

Next we receive the text to be centered as the "myText" variable. Note that C/C++ like to use pointers, so technically we receive a pointer to the data from the RPG program. The length is passed in as the 2nd parameter. C/C++ support "pass by reference" as used on the first parameter, and "pass by value" which is used for the 2nd parameter. Note the "VALUE" keyword on the RPG IV Prototype for the 2nd parameter. If the RPG prototype omitted the VALUE keyword or used CONST instead, then the 2nd parameter would also be passed by reference, and it would appear as "int* textLen". C/C++ use the * to indicate that a pointer is being declared.

The routine itself is just grunt code--nothing special. We copy the input data into a string variable, strip off all leading and trailing blanks (more on the trim() function next time) and then simply divide the remaining space by 2 and front-load the return value with that many blanks--copying the original data immediately behind it. That trim(text); line of code isn't strictly necessary if the data coming into the routine is already left-adjusted. But it also strips off trailing blanks to determing the length of the text inside the field before calculating were the center point is. We'll cover trim, ltrim, and rtrim next time.

Done! Now you have a CENTERTEXT function you can use in RPG IV.

To compile this *MODULE, use the C++ compiler. To do that in PDM or RDi make sure the SEU type is CPP. If it is only C, you'll have the opportunity to try again.

Since the extern "C" keyword is used, RPG will be able to find the function in this module, provided it is specified either in a Binding Directory that is part of that RPG program's H spec, or the CENTERTEXT module is specified on the MODULE parameter of the CRTPGM command. More on this next time.

 

 

 

Return to midrangenews.com home page.
Sort Ascend | Descend

COMMENTS