Line: 1 to 1 | |||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Dynamic Linking and the CALL StatementContents : | |||||||||||||||||||||||||||||||||||||
Line: 7 to 7 | |||||||||||||||||||||||||||||||||||||
Calling External Functions from APPX ILF Code | |||||||||||||||||||||||||||||||||||||
Deleted: | |||||||||||||||||||||||||||||||||||||
< < | |||||||||||||||||||||||||||||||||||||
It is possible for system integrators to develop and compile functions(typically in a 3GL like C) which can be called from APPX ILF code, to provide custom functionality which is not available in the APPX engine itself. | |||||||||||||||||||||||||||||||||||||
Changed: | |||||||||||||||||||||||||||||||||||||
< < | Because linking effectively makes your functions "part" of the APPX engine execution environment, no "safety nets" can be put in place to prevent coding errors in your functions (for example, improper use of pointers) from affecting the APPX run-time environment. Likewise, since the address space of your extension is shared with APPX, an error in your code can affect the APPX engine even after your extension has completed execution. | ||||||||||||||||||||||||||||||||||||
> > | Because linking effectively makes your functions "part" of the APPX engine execution environment, no "safety nets" can be put in place to prevent coding errors in your functions (for example, improper use of pointers) from affecting the APPX run-time environment. | ||||||||||||||||||||||||||||||||||||
Merely that you've tested the function and seen that it does produce the results you've expected does not guarantee that the function is bug-free, because unintended (and undetected) side effects may be occurring. Therefore, writing functions to be called from APPX should only be attempted by those who have a solid level of understanding of, and skill in, the language they are using to write those functions, and the platform (UNIX, Windows, VMS) on which they will run. APPX Software cannot be responsible for errors occurring as a result of improperly written, compiled, or CALLed external functions, so please program with care. | |||||||||||||||||||||||||||||||||||||
Changed: | |||||||||||||||||||||||||||||||||||||
< < | Since the address space of your extension is shared with APPX, an error in your code can affect the APPX engine even after your extension has completed execution | ||||||||||||||||||||||||||||||||||||
> > | Also see Calling Windows API Functions for more examples of interfacing with external libraries. Since the address space of your extension is shared with APPX, an error in your code can affect the APPX engine even after your extension has completed execution | ||||||||||||||||||||||||||||||||||||
Dynamic Linking | |||||||||||||||||||||||||||||||||||||
Changed: | |||||||||||||||||||||||||||||||||||||
< < | With APPX version 3.4, a new interface to CALLing external functions was introduced: Dynamic linking. This document describes how to take advantage of this new capability in APPX. (Previously, dynamic linking was available only on VMS, AIX and Windows platforms.) | ||||||||||||||||||||||||||||||||||||
> > | With APPX version 3.4 & up, a new interface to CALLing external functions was introduced: Dynamic linking. This document describes how to take advantage of this new capability in APPX. (Previously, dynamic linking was available only on VMS, AIX and Windows platforms.) | ||||||||||||||||||||||||||||||||||||
With "static" linking, a developer had to create a new APPX executable, from the appx.a library and a customized call.c module. The better way is "dynamic" linking, which is a way of combining functions in an external function library, with the APPX executable at run-time, WITHOUT end-user rebuilding of the APPX executable. This makes it much easier for C developers to extend the functionality of APPX, without needing detailed knowledge of how APPX loads and runs user-provided functions, and without the error-prone activity of maintaining the function pointer table. Using dynamic linking, if a C developer wants to make a new CALLable function available to APPX designers, all he/she needs to do is compile it (using platform- specific instructions listed below) then tell the APPX designers the name of the function and the full path to the binary library file containing it. An example of how an APPX designer would call a dynamically-linked function called "func", which the C programmer compiled into the library "/appx/callee", and which takes one integer parameter, would be: | |||||||||||||||||||||||||||||||||||||
Deleted: | |||||||||||||||||||||||||||||||||||||
< < | |||||||||||||||||||||||||||||||||||||
SET --- AI 99 PASS --- AI FIELD SHARE? Y CALL /appx/callee,func RESIDENT? N END? N FAIL 0 | |||||||||||||||||||||||||||||||||||||
Line: 43 to 41 | |||||||||||||||||||||||||||||||||||||
(You are not required to use the C language to create a shared function library. Any language which supports the creation of shared libraries whose functions can be called by ordinary C programs on that platform should be able to be used. Note that if you choose another language, you will be on your own to figure out how to structure your code to accept parameters passed by APPX, and how to compile the resulting functions into a library.) For purposes of an example, we will show the commands used to create a binary file containing the 'func' function, from the following C code: | |||||||||||||||||||||||||||||||||||||
Deleted: | |||||||||||||||||||||||||||||||||||||
< < | |||||||||||||||||||||||||||||||||||||
$ more callee.c #include <stdio.h> | |||||||||||||||||||||||||||||||||||||
Line: 68 to 64 | |||||||||||||||||||||||||||||||||||||
You can store one, or many, functions in a dynamically-linked module. Whatever makes sense for your application. The following are the cc and ld lines required to compile the above file, callee.c, into a 'callee' binary, whose 'func' function can be access from APPX as described in the ILF code listed above. You can substitute any name for "callee", as desired. | |||||||||||||||||||||||||||||||||||||
Deleted: | |||||||||||||||||||||||||||||||||||||
< < | |||||||||||||||||||||||||||||||||||||
Solaris, SCO, Unixware, DG/UX, NCR:
$ cc -o callee -G callee.c | |||||||||||||||||||||||||||||||||||||
Deleted: | |||||||||||||||||||||||||||||||||||||
< < | |||||||||||||||||||||||||||||||||||||
Linux:
$ cc -o callee -shared callee.c | |||||||||||||||||||||||||||||||||||||
Deleted: | |||||||||||||||||||||||||||||||||||||
< < | |||||||||||||||||||||||||||||||||||||
HP/UX:
$ cc -Aa +z -c callee.c $ ld -b -o callee callee.o | |||||||||||||||||||||||||||||||||||||
Deleted: | |||||||||||||||||||||||||||||||||||||
< < | |||||||||||||||||||||||||||||||||||||
AIX:
$ cat callee.exp #! | |||||||||||||||||||||||||||||||||||||
Line: 94 to 82 | |||||||||||||||||||||||||||||||||||||
$ cc -c callee.c $ cc -g -o callee -bE:callee.exp callee.o | |||||||||||||||||||||||||||||||||||||
Deleted: | |||||||||||||||||||||||||||||||||||||
< < | |||||||||||||||||||||||||||||||||||||
Special AIX instructions: Under AIX, you must create an 'exports' file that lists the functions you want to call. My file was called 'callee.exp' and lists one function. The first line contains "#!" and the succeeding lines contain "functionname"<RETURN>. An example of what this file would look like when cat'd is below, as is the command line you would use to set up the exported functions in callee.
After issuing the proper compile instructions for your platform, you will end up with a shared library called 'callee' (or whatever other name you used instead of 'callee'). Again, it can be named whatever you like (the '-o callee' argument determines the name of the library).
For the Windows Programmer | |||||||||||||||||||||||||||||||||||||
Deleted: | |||||||||||||||||||||||||||||||||||||
< < | |||||||||||||||||||||||||||||||||||||
Compiling External Functions For Dynamic Linking On the Windows platform, APPX can dynamically invoke any function which exists in a standard Windows DLL, which has been created using the standard C (rather than C++) linking conventions. (In particular, this is not the same thing as an ActiveX DLL.) APPX expects any DLL-based functions to have been compiled to use the _stdcall (another term for this is WINAPI), rather than _cdecl, calling conventions. Refer to your compiler documentation, for how to ensure that your functions meet this requirement. | |||||||||||||||||||||||||||||||||||||
Line: 114 to 98 | |||||||||||||||||||||||||||||||||||||
Guidelines for Designing Functions to be Called by APPX | |||||||||||||||||||||||||||||||||||||
Deleted: | |||||||||||||||||||||||||||||||||||||
< < | |||||||||||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||||||||||
Changed: | |||||||||||||||||||||||||||||||||||||
< < |
| ||||||||||||||||||||||||||||||||||||
> > |
| ||||||||||||||||||||||||||||||||||||
For the APPX Programmer | |||||||||||||||||||||||||||||||||||||
Deleted: | |||||||||||||||||||||||||||||||||||||
< < | Using CALLable functions in APPX | ||||||||||||||||||||||||||||||||||||
To CALL a dynamically linked function, you specify the name of the library file containing the function, followed by a comma ',', followed by the function name. Note: The function name may have a "." or "_" prepended by the compiler on some platforms, which you will have to include in the function name, if it's there. In UNIX, you can find out for sure what the compiler did to the function names with a command like: nm /appx/callee | grep func "nm" lists several columns of information about the symbols in the function library. If you see ".func" or "_func" instead of "func", in the first column of the output, then use that variation on the function name instead. For example, to CALL the 'func' function in the /appx/callee file from APPX, use code like: | |||||||||||||||||||||||||||||||||||||
Deleted: | |||||||||||||||||||||||||||||||||||||
< < | |||||||||||||||||||||||||||||||||||||
SET --- AI 99 PASS --- AI FIELD SHARE? N CALL /appx/callee,func RESIDENT? N END? N FAIL 0 | |||||||||||||||||||||||||||||||||||||
Line: 158 to 136 | |||||||||||||||||||||||||||||||||||||
This will perform "pass by value", sending the actual variable value rather than its address. You can be confident that, unless the function you are calling has a bug that results in unpredictable memory over-writes, the value of the variable in APPX will not change, if you pass it "SHARE? N". (However, the function must be written to expect "SHARE? N" for that parameter. You cannot just arbitrarily change the value of the SHARE? flag and expect the function to work properly.) The field that you PASS should be a be a 4-byte binary field for "int" and "long" C data types, and a 2-byte binary field for the "short" data type. | |||||||||||||||||||||||||||||||||||||
Changed: | |||||||||||||||||||||||||||||||||||||
< < | If your CALLed function expects a parameter which is a "char *" (that is, a C string), and it DOES NOT want to modify the original APPX alpha or text field's value, set "SHARE?" to "N" when you PASS it. This will cause a pointer to a null-terminated copy of that APPX field to be passed to the CALLed function. "Null-terminated" means that a hex '00' character is appended to the end of the copy of the field. This is the C convention for working with character strings. The field that you PASS should be a be a 4-byte binary field for "int" and "long" C data types, and a 2-byte binary field for the "short" data type. | ||||||||||||||||||||||||||||||||||||
> > | If your CALLed function expects a parameter which is a "char *" (that is, a C string), and it DOES NOT want to modify the original APPX alpha or text field's value, set "SHARE?" to "N" when you PASS it. This will cause a pointer to a null-terminated copy of that APPX field to be passed to the CALLed function. "Null-terminated" means that a hex '00' character is appended to the end of the copy of the field. This is the C convention for working with character strings. | ||||||||||||||||||||||||||||||||||||
Changed: | |||||||||||||||||||||||||||||||||||||
< < | If your CALLed function expects a parameter which is a "char " (that is, a C string), and it *DOES want to modify the original APPX alpha or text field's value, set "SHARE?" to "Y" when you PASS it. This will cause a pointer to the actual APPX field to be passed to the CALLed function. IT WILL NOT BE NULL-TERMINATED, so the writer of the C function must be careful when working with it. | ||||||||||||||||||||||||||||||||||||
> > | If your CALLed function expects a parameter which is a "char " (that is, a C string), and it DOES want to modify the original APPX alpha or text field's value, set "SHARE?" to "Y" when you PASS it. This will cause a pointer to the actual APPX field to be passed to the CALLed function. IT WILL NOT BE NULL-TERMINATED, so the writer of the C function must be careful when working with it. | ||||||||||||||||||||||||||||||||||||
If you PASS an APPX FILE, what the C program will receive is the full-path-name of the file, represented as a C character string. It does not receive any sort of open file pointer, record number, or record contents. | |||||||||||||||||||||||||||||||||||||
Line: 174 to 152 | |||||||||||||||||||||||||||||||||||||
Here is a list of how C types correspond to APPX data types and PASS share flags: | |||||||||||||||||||||||||||||||||||||
Changed: | |||||||||||||||||||||||||||||||||||||
< < |
| ||||||||||||||||||||||||||||||||||||
> > |
| ||||||||||||||||||||||||||||||||||||
(1) Pass with SHARE? N to send a pointer to a null-terminated read-only copy of the field to the C function. Pass with SHARE? Y to send a pointer to the actual APPX field, so that the C function can modify it.
(2) Use "unsigned" if the APPX numeric field has been declared as "Signed? N" at the data dictionary level, and omit it if the APPX field has been declared as "Signed? Y" at the data dictionary level.
How do I pass a parameter to the C routine and get a result back? | |||||||||||||||||||||||||||||||||||||
Changed: | |||||||||||||||||||||||||||||||||||||
< < | You can use the same example as above, with some very minor adjustments. (Changes are in red): | ||||||||||||||||||||||||||||||||||||
> > | You can use the same example as above, with some very minor adjustments. (Changes are in red): | ||||||||||||||||||||||||||||||||||||
#include <stdio.h> #ifdef __cplusplus | |||||||||||||||||||||||||||||||||||||
Line: 208 to 177 | |||||||||||||||||||||||||||||||||||||
{ #endif | |||||||||||||||||||||||||||||||||||||
Changed: | |||||||||||||||||||||||||||||||||||||
< < | void func( int * x ) | ||||||||||||||||||||||||||||||||||||
> > | void func( int * x ) | ||||||||||||||||||||||||||||||||||||
{ | |||||||||||||||||||||||||||||||||||||
Changed: | |||||||||||||||||||||||||||||||||||||
< < | printf( "inside of func - called with %d\n", *x ); | ||||||||||||||||||||||||||||||||||||
> > | printf( "inside of func - called with %d\n", *x ); | ||||||||||||||||||||||||||||||||||||
} | |||||||||||||||||||||||||||||||||||||
Line: 220 to 189 | |||||||||||||||||||||||||||||||||||||
You must also change the "SHARE?" flag from 'N' to 'Y' on the PASS:
SET --- AI 99 | |||||||||||||||||||||||||||||||||||||
Changed: | |||||||||||||||||||||||||||||||||||||
< < | PASS --- AI FIELD SHARE? Y | ||||||||||||||||||||||||||||||||||||
> > | PASS --- AI FIELD SHARE? Y | ||||||||||||||||||||||||||||||||||||
CALL /appx/callee,func RESIDENT? N END? N FAIL 0 The result of calling this function is that --- AI should be set to 55. | |||||||||||||||||||||||||||||||||||||
Changed: | |||||||||||||||||||||||||||||||||||||
< < | Call statement continued | ||||||||||||||||||||||||||||||||||||
> > | |||||||||||||||||||||||||||||||||||||
Comments:Read what other users have said about this page or add your own comments. | |||||||||||||||||||||||||||||||||||||
Changed: | |||||||||||||||||||||||||||||||||||||
< < | |||||||||||||||||||||||||||||||||||||
> > |
Line: 1 to 1 | |||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Added: | |||||||||||||||||||||||||||||||||||||||
> > |
Dynamic Linking and the CALL StatementContents :Calling External Functions from APPX ILF CodeIt is possible for system integrators to develop and compile functions(typically in a 3GL like C) which can be called from APPX ILF code, to provide custom functionality which is not available in the APPX engine itself. Because linking effectively makes your functions "part" of the APPX engine execution environment, no "safety nets" can be put in place to prevent coding errors in your functions (for example, improper use of pointers) from affecting the APPX run-time environment. Likewise, since the address space of your extension is shared with APPX, an error in your code can affect the APPX engine even after your extension has completed execution. Merely that you've tested the function and seen that it does produce the results you've expected does not guarantee that the function is bug-free, because unintended (and undetected) side effects may be occurring. Therefore, writing functions to be called from APPX should only be attempted by those who have a solid level of understanding of, and skill in, the language they are using to write those functions, and the platform (UNIX, Windows, VMS) on which they will run. APPX Software cannot be responsible for errors occurring as a result of improperly written, compiled, or CALLed external functions, so please program with care. Since the address space of your extension is shared with APPX, an error in your code can affect the APPX engine even after your extension has completed executionDynamic LinkingWith APPX version 3.4, a new interface to CALLing external functions was introduced: Dynamic linking. This document describes how to take advantage of this new capability in APPX. (Previously, dynamic linking was available only on VMS, AIX and Windows platforms.) With "static" linking, a developer had to create a new APPX executable, from the appx.a library and a customized call.c module. The better way is "dynamic" linking, which is a way of combining functions in an external function library, with the APPX executable at run-time, WITHOUT end-user rebuilding of the APPX executable. This makes it much easier for C developers to extend the functionality of APPX, without needing detailed knowledge of how APPX loads and runs user-provided functions, and without the error-prone activity of maintaining the function pointer table. Using dynamic linking, if a C developer wants to make a new CALLable function available to APPX designers, all he/she needs to do is compile it (using platform- specific instructions listed below) then tell the APPX designers the name of the function and the full path to the binary library file containing it. An example of how an APPX designer would call a dynamically-linked function called "func", which the C programmer compiled into the library "/appx/callee", and which takes one integer parameter, would be:SET --- AI 99 PASS --- AI FIELD SHARE? Y CALL /appx/callee,func RESIDENT? N END? N FAIL 0When APPX runs this section of ILF code, it knows how to go out and find the UNIX file /appx/callee, then locate the function "func" which is stored inside it. If you are calling a function in a Windows DLL, you would use a Windows-style pathname for the library, like "F:\appx\callee,func" instead of "/appx/callee,func". In addition to the benefit of it being easier to add new functions to APPX via "dynamic" linking than via the old static linking method, there is another significant benefit: When a new release of APPX is introduced, no re-linking is required. The new engine will dynamically locate and run the code, just as the old one did. (Of course, there may be details specific to your code that would cause it not to run under a new version of APPX, but we expect that most user-written functions would be unaffected by an upgrade.) For the UNIX C ProgrammerCompiling External Functions For Dynamic Linking Here is a list of the C compiler flags you need on each platform in order to be able to compile a dynamically called function. Please note that customers may have different compilers and/or different compiler versions and the following information may not be appropriate for all customers. The following configurations have been tested by APPX, and may or may not work at any specific customer site. (You are not required to use the C language to create a shared function library. Any language which supports the creation of shared libraries whose functions can be called by ordinary C programs on that platform should be able to be used. Note that if you choose another language, you will be on your own to figure out how to structure your code to accept parameters passed by APPX, and how to compile the resulting functions into a library.) For purposes of an example, we will show the commands used to create a binary file containing the 'func' function, from the following C code:$ more callee.c #include <stdio.h> #ifdef __cplusplus extern "C" { #endif void func( int x ) { printf( "inside of func - called with %d\n", x ); } #ifdef __cplusplus } #endifBefore continuing, note that this really is all that you need in your C program in order to allow APPX to access 'func'. No external declarations of APPX structures or APPX typedefs, etc. Not even a 'main'. The #ifdef's above take care of telling a C++ compiler not to mangle the symbol names in this file as it is compiled. APPX expects C-style names, not those that have been altered in the usual C++ way. You can store one, or many, functions in a dynamically-linked module. Whatever makes sense for your application. The following are the cc and ld lines required to compile the above file, callee.c, into a 'callee' binary, whose 'func' function can be access from APPX as described in the ILF code listed above. You can substitute any name for "callee", as desired. Solaris, SCO, Unixware, DG/UX, NCR: $ cc -o callee -G callee.cLinux: $ cc -o callee -shared callee.cHP/UX: $ cc -Aa +z -c callee.c $ ld -b -o callee callee.oAIX: $ cat callee.exp #! func $ cc -c callee.c $ cc -g -o callee -bE:callee.exp callee.oSpecial AIX instructions: Under AIX, you must create an 'exports' file that lists the functions you want to call. My file was called 'callee.exp' and lists one function. The first line contains "#!" and the succeeding lines contain "functionname"<RETURN>. An example of what this file would look like when cat'd is below, as is the command line you would use to set up the exported functions in callee. After issuing the proper compile instructions for your platform, you will end up with a shared library called 'callee' (or whatever other name you used instead of 'callee'). Again, it can be named whatever you like (the '-o callee' argument determines the name of the library). For the Windows ProgrammerCompiling External Functions For Dynamic Linking On the Windows platform, APPX can dynamically invoke any function which exists in a standard Windows DLL, which has been created using the standard C (rather than C++) linking conventions. (In particular, this is not the same thing as an ActiveX DLL.) APPX expects any DLL-based functions to have been compiled to use the _stdcall (another term for this is WINAPI), rather than _cdecl, calling conventions. Refer to your compiler documentation, for how to ensure that your functions meet this requirement. The rather complex subject of writing a Win32 DLL is beyond the scope of this document. Please consult a Win32 programming book for details of how to develop and compile a DLL that can be accessed from a Win32 C program. Standard techniques for writing DLL's apply. As with the UNIX shared library creation process, the DLL can be written in any language that supports creation of the proper type of DLL. This document includes descriptions of how to map APPX data types to standard C data types. If you choose another implementation language, you will be on your own to figure out how to structure your code to accept parameters passed by APPX, and how to compile the resulting functions into a library.Guidelines for Designing Functions to be Called by APPX
For the APPX ProgrammerUsing CALLable functions in APPX To CALL a dynamically linked function, you specify the name of the library file containing the function, followed by a comma ',', followed by the function name. Note: The function name may have a "." or "_" prepended by the compiler on some platforms, which you will have to include in the function name, if it's there. In UNIX, you can find out for sure what the compiler did to the function names with a command like: nm /appx/callee | grep func "nm" lists several columns of information about the symbols in the function library. If you see ".func" or "_func" instead of "func", in the first column of the output, then use that variation on the function name instead. For example, to CALL the 'func' function in the /appx/callee file from APPX, use code like:SET --- AI 99 PASS --- AI FIELD SHARE? N CALL /appx/callee,func RESIDENT? N END? N FAIL 0This would pass the integer value 99 to the called function. The APPX designer should PASS one argument for each parameter required by the C function he/she is CALLing. The PASS statements should correspond to the order in which parameters are listed in the C function declaration. (See the function's developer for details.) Be aware that if you change the data type, size (or if PASSing an entire RECORD structure, the offset) of a field being PASSed, via the APPX Data Dictionary, any external function in which that field is used should be reviewed, and any necessary changes should be made to it, in order to accommodate the change in the field definition. Specific attention should be paid to the SHARE? flag values set in PASS statements, because whether they should be set to Y or N depends on how the C function was declared. (The original developer of the C function you are CALLing is the best source for information on this.) In general, if you want to pass a copy of the original APPX field, because you do not need to modify that field in the C function, you should set "SHARE?" to "N". If you want to pass the original APPX field itself, and DO expect to modify that field in the C function, you should set "SHARE?" to "Y". In all cases, you must coordinate with the writer of the C function, to make sure both of you agree on which parameters are shared and which are not. If your SHARE? values don't match what the C programmer expected, the function will not work properly. More details on what "SHARE?" means, for various data types, follow. If your CALLed function expects a parameter which is a pointer to an unsigned integer or long, set "SHARE?" to "Y" when you PASS it. This will perform "pass by reference", sending the address of the variable to your function, instead of sending its value. One of the ways this is useful is that a CALLed function can modify that value, perhaps by doing an elaborate mathematical calculation, so that a new value is reflected in that variable when you return to APPX. If your CALLed function expects a parameter which is an actual unsigned integer, long or short, set "SHARE?" to "N" when you PASS it. This will perform "pass by value", sending the actual variable value rather than its address. You can be confident that, unless the function you are calling has a bug that results in unpredictable memory over-writes, the value of the variable in APPX will not change, if you pass it "SHARE? N". (However, the function must be written to expect "SHARE? N" for that parameter. You cannot just arbitrarily change the value of the SHARE? flag and expect the function to work properly.) The field that you PASS should be a be a 4-byte binary field for "int" and "long" C data types, and a 2-byte binary field for the "short" data type. If your CALLed function expects a parameter which is a "char *" (that is, a C string), and it DOES NOT want to modify the original APPX alpha or text field's value, set "SHARE?" to "N" when you PASS it. This will cause a pointer to a null-terminated copy of that APPX field to be passed to the CALLed function. "Null-terminated" means that a hex '00' character is appended to the end of the copy of the field. This is the C convention for working with character strings. The field that you PASS should be a be a 4-byte binary field for "int" and "long" C data types, and a 2-byte binary field for the "short" data type. If your CALLed function expects a parameter which is a "char " (that is, a C string), and it *DOES want to modify the original APPX alpha or text field's value, set "SHARE?" to "Y" when you PASS it. This will cause a pointer to the actual APPX field to be passed to the CALLed function. IT WILL NOT BE NULL-TERMINATED, so the writer of the C function must be careful when working with it. If you PASS an APPX FILE, what the C program will receive is the full-path-name of the file, represented as a C character string. It does not receive any sort of open file pointer, record number, or record contents. You can also PASS packed-decimal fields and date fields, but it is up to you to "decode" the APPX internal format. Needless to say, we recommend passing numeric values in binary form, and dates in (probably) character string form (convert the date to alpha before PASSing the alpha) rather than using the APPX internal formats for these fields. It is also possible to PASS the actual data file record (so that you can modify it) or a copy of that record (just for reading). Again, be careful doing this, because when an APPX designer changes the record layout, the C function will malfunction in unpredictable ways. The record layout will match what is described in techdoc, in terms of offsets into the record and lengths for each field. No conversions of data are performed when a record is PASSed, and there is no way to verify from within the C function that the size and layout of the PASSed record matches what the function was written to expect. Finally, many C functions provide their callers with a "return code" value. If your CALLed function sets its return code to indicate various completion statuses, you can examine the 32-bit value returned by it (if any) by inspecting the APPX PDF "--- RETURN CODE". Here is a list of how C types correspond to APPX data types and PASS share flags:
How do I pass a parameter to the C routine and get a result back?You can use the same example as above, with some very minor adjustments. (Changes are in red):#include <stdio.h> #ifdef __cplusplus extern "C" { #endif void func( int * x ) { printf( "inside of func - called with %d\n", *x ); } #ifdef __cplusplus } #endifYou must also change the "SHARE?" flag from 'N' to 'Y' on the PASS: SET --- AI 99
PASS --- AI FIELD SHARE? Y
CALL /appx/callee,func RESIDENT? N END? N FAIL 0
The result of calling this function is that --- AI should be set to 55.
Call statement continuedComments:Read what other users have said about this page or add your own comments. |