|
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 mailing list archive is Copyright 1997-2025 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.