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



Hi Mark,

On Wed, 24 Apr 2002 Mark.Scheele@xxxxxxxx.com wrote:
>
> Thank you so much for providing the RPGLE sockets programming tuturial.
> I found it extremely valuable.

Great -- I'm glad you found it useful!

> There is one mystery I haven't been able
> to solve though; how are the unix-like APIs brought into the rpg ILE
> program? Or put another way, how does the ILE program know where to find
> these APIs? I have found the QSYSINC library and guess that the file "H"
> is maybe the include file equivalent containing the functions, but what

QSYSINC contains nothing for UNIX-Type APIs, unless you're coding in C.
In other words, there is no RPG code for the UNIX-Type APIs in QSYSINC.
(Though, there is RPG code for many of the other system APIs)

Instead of QSYSINC, I've written my own equivalent of the members in
QSYSINC called "SOCKET_H".   The details of what is put in this file
is explained throughout the tutorial -- in fact, much of the tutorial
dwells on how to create this file by converting from C to RPG.

The idea of putting this data into a "header file" is first introduced
here:
   http://klement.dstorm.net/rpg/socktut/improvedclient.html#AEN461

On that page, it says:

   ". . . our example contains about 75 lines of code that
    are simply prototypes, constants and data structures which will be
    used in  just about every program that we write using sockets. One way
    that we can improve our program is to place them into their own source
    member, use the /copy compiler directive to add them into our
    programs."

This is EXACTLY what QSYSINC does for C programmers, and what it does
for RPG programs for other (not UNIX-type) APIs.

You will not that it does not contain the APIs themselves, and has
nothing to do with "bringing the APIs into the program" or "finding the
APIs", they're just the definitions needed when calling the APIs.
I'll explain how it finds the actual APIs towards the end of this message.

> in the RPGLE code is directing it to the QSYSINC library and whatever
> header file that contains the socket() and other APIs?

Well, as I said we don't use QSYSINC.  If you download the save file
from my web site, and are using the header member that I created
(SOCKET_H) then the code that directs it to use that header member
is this line:

     D/copy socktut/qrpglesrc,socket_h

>
> I just dont see the link. The QSYSINC library is as far as I could trace
> this in the IBM documentation.
>

IBM does not supply definitions or documentation for RPG programmers
wanting to use sockets.   The C source member that corresponds (well,
more or less) to my SOCKET_H is in file QSYSINC/SYS, member SOCKET.  But
you won't find the RPG equiv in IBM docs because IBM does not give
definitions for RPG programmers.   For that, you either have to write
your own definitions or use the ones that I wrote (mentioned above).

Okay, hopefully now you understand the relationship between QSYSINC and
your programs, and IBM's docs.   Now to explain how it finds the APIs
themselves...

ILE programs (in any language, C, RPG, COBOL, CL) can be made up of many
different pieces.   "modules", "service programs", and "programs" are the
basic pieces that make up an ILE application.

Each module is created by taking source code and compiling it.  You do
this using the CRTCMOD, CRTRPGMOD, CRTCBLMOD, CRTCLMOD commands...  These
modules are now compiled down to machine-readable code.   However, these
modules are not "bound" to anything...

That is, the compiled module code knows it's calling a procedure called
"socket" or "connect" (or your own names procedure names, or whatever) but
doesn't know where those procedures are.   They could be located in other
modules, or in service programs, or even in the same program, at the
module stage, it does not know.   All it knows is the NAMES of the
procedures.

(TIP: These symbolic procedure names are referred to as "symbols."   So
if you ever get an error like "Definition not found for symbol 'socket'"
that means that it can't find the procedure that you're trying to call)

The next step you take, after compiling the modules is to "bind" the
modules.   (Or, in Unix or Windows or any other platform in the world,
this step is called "linking", but it's the same thing...)  This is where
the symbol names are resolved to actual procedures in service programs
or other modules, etc.  A procedure that's in a module that's bound
into the same *PGM object is said to be "bound by copy", since a copy
of the procedure itself is in the program that you're running.   A
procedure in a service program is said to be "bound by reference",
since all the *PGM object contains is a reference to the *SRVPGM.

When you use the CRTBNDRPG command, it simplifies these two steps for
you by first compiling the MODULE into the QTEMP library, and then
BINDING it... all in one easy step...

So how does the system know which modules & service programs to search
when binding your program?   Well, you CAN specify the modules and
service programs individually on the CRTPGM command.   But, an easier
way is to define a "binding directory."   A binding directory is nothing
more than a list of modules and/or service programs that the system
will use when it takes your symbols and resolves them to objects on
disk.

I know this message is getting long... :)  But, we're almost there!

You can specify binding directories on both the CRTBNDRPG command and
the CRTPGM command.  Plus, there are a few "default" binding directories
that the system will bind to without you manually specifying them.  One
of these "default" binding directories is called QUSAPIBD and contains a
list of IBM-supplied service programs that implement APIs.   And that's
the key to how it finds the UNIX-Type APIs!

try typing:  WRKBNDDIRE QSYS/QUSAPIBD

Scroll down the list, and you'll see some service programs called
QSOSRV1, QSOSRV2, etc.  These are the actual service programs that contain
the sockets functions.  Some of the other service programs contain the
other UNIX-type APIs.

To prove this, type:  DSPSRVPGM SRVPGM(QSOSRV1) DETAIL(*PROCEXP)

(The "DETAIL(*PROCEXP)" means that the only details I want are the
procedures that are exported...   you can omit the DETAIL(*PROCEXP) if
you want more information, but be aware that there are several screens
of info, each multiple pages long...)

Likewise, you can see exactly which service programs the system bound into
the program that you created by typing (for example):

      DSPPGM PGM(SOCKTUT/CLIENTEX1) DETAIL(*SRVPGM)

You'll see that QSOSRV1 & QSOSRV2 are listed as service programs that it
bound to.   If you run the same command on an ILE program that does not
use sockets at all, you'll see that those two service programs did not
get bound (because sockets werent needed).

Well, I hope that explains everything... :)  (probably explains too much)
I'm going to CC: this to the RPG400-L mailing list over at midrange.com.
There's a number of people there who are just learning ILE who will
probably find this information enlightening as well.

HTH




As an Amazon Associate we earn from qualifying purchases.

This thread ...


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.