epilogue: I4GL / C parameter passing
Posted in 1993
Fellow netters, This is a summary of information I gleaned from an earlier thread, relating to using C functions with an Informix 4GL program. If you do not do or plan to do such mixed programming, then this message may not be of interest to you. First off, many thanks to Jonathan Leffler of Informix, who provided or con- firmed much of the information below. Second, the Informix documentation is pretty good on this point. I refer readers to the section "C Functions" in chapter 2 "Informix-4GL Programming" of the _Informix-4GL Reference Manual-Volume 1_. In the version 4.00 manual it is pages 2-64 thru 2-69. My one objection is that it is in the index under "Functions, C language" but NOT cross-referenced under "C language functions". Since I tend to go to the index, rather than the table of contents, I missed this section the first time around. Third, a summary of the details: 1. Informix uses a stack for passing parameters between functions. This is separate from "THE" stack used by C and the operating system for passing parameters. In a function call such as: CALL myfunc ( a, b, c ) RETURNING d, e the calling routine pushes the parameters onto the Informix stack in left to right order, i.e,, first a, then b, then c. It then passes the number of Informix parameters as the only C parameter; in this case, 3 is passed. 2. Informix functions always check that the number of parameters is correct. One minor optimization available to the C programmer is to omit this check, recognizing that you won't be warned if the parameter stack gets "out of sync". 3. The called function must pop the parameters from the stack in right to left order. Informix provides a set of "popxxx()" functions, where xxx is the type of the parameter. The documentation suggests that the data types should match in the calling and called functions. I have found that you can use COMPATIBLE types freely, subject to obvious size limits. For example, it has always worked for me to pass a SMALLINT and then pop it into an INTEGER using popint(). Using popshort() to pop an INTEGER into a short (SMALLINT), should work for values in the range of a SMALLINT. 4. The called C function must push its return values onto the Informix stack left to right; in the example, push d before e. Use the Informix-provided "retxxx()" functions, where xxx is once again the type. The called function must then "return" the number of such parameters; in this example "return(2)". 5. If your C function calls an Informix function, use "pushxxx()" to push parameters onto the stack, left to right, and "popxxx()" to fetch return values right to left. Remember to pass the number of input parameters, though you may choose to bypass checking the number of return parameters. Thus the C equivalent of calling 'myfunc' above is: pushxxx(a); pushxxx(b); pushxxx(c); if ( myfunc(3) != 2 ) { /* complain and/or stop */ } popxxx(&e); popxxx(&d); 6. An important thing to remember is that "retquote()" and "pushquote()" for managing Informix CHAR / C char* variables are NOT equivalent. [This was the error in my original "translate()" function.] Whew! That turned out longer than I expected. I hope you find it useful. Regards, Alan ___________________________ ______________________| R. Alan Popiel |__________________________ \\ Internet: | Martin Marietta, SLS | / \\ alan@den.mmc.com | P.O. Box 179, M/S 3810 | Std disclaimers apply. / )Voice: | Denver, CO 80201-0179 USA | ( / 303-977-9998 |___________________________| (But you knew that!) \\ /________________________) (____________________________\\