Compiled API Extensions are stored within dynamic link libraries (DLLs) which are loaded upon demand by PowerWeb.
Compiled API Extensions can be used as a faster and more flexible alternative to CGI, providing a tight integration with PowerWeb. The API Interface functions allow you access to PowerWeb's internal engine and configuration settings, giving you a powerful robust server application development environment.
PowerWeb also allows you to extend its internal engine by defining API Hooks which selectively override aspects of its behaviour, such as user authentication and access control. When you write these hooks in a compiled language, you are extending PowerWeb with no performance penalty - your extensions are seamlessly integrated into the main engine.
With PowerWeb's multi-language API support, you can prototype your application or extension within Perl or Rexx, and then choose a final delivery language. In most cases, Perl or Rexx will be fast enough, but for time-critical applications, a compiled language such as C has not only the lowest load-time overhead, but also executes faster.
All C-compatible functions called by PowerWeb Server++ have the following definition:
typedef long (*pfnAPI)(void* parcel);
Your Compiled Extension is expected to return an integer result indicating the success or failure of your script, according to the following table:
You should also ensure that "\powerweb\system\include" is on your INCLUDE path and that "\powerweb\system\lib" is on your LIB path. Refer to the file "\powerweb\system\tour\source\tour.nmk" for a sample NMAKE script.
You will need to link your DLL with the "PowerAPI.Lib" library module which is found in the "\powerweb\system\lib" directory. Function prototypes for all the PowerWeb API interface functions are found in "\powerweb\system\include\PowerAPI.hpp".
IBM CSet++ or VisualAge C++ compiler:
IBM's CSet++ compiler uses the compiler switches:
/Gd+ /Ge- /Gm+
For a complete example, see the "\powerweb\system\tour\source" directory which includes make files and header files.
Watcom C++ version 10 compiler:
Watcom 10.x uses the following Compiler switches:
-bm multithreaded
-bd dll
-otexan maximum optimisation
-5r Pentium optimized and register calling convention
system os2v2 dll initinstance terminstance # # object file(s) # file YourFile.obj # # the DLL name # name YourLib.dll library powerapi.lib # # the module name in upper case # option modname=YOURLIB # # The following are VERY IMPORTANT to ensure # your DLL does not conflict with the main # PowerWeb DLLs. # option manyautodata option caseexact segment type code loadoncall shared segment type data loadoncall nonshared readwrite # # the exported functions... case sensitive! # export YourFunctionCall
Suggested Location for C Modules: Assuming your server root is "\powerweb", put your library DLL in the directory "\powerweb\bin", so that you can load it with the URL "/bin/module!function" where "module" is the name of your DLL (without the file extension) and "function" is the name of the function within your DLL to call.
Example URL: "/bin/property!ShowMenu"
PowerWeb automatically adds the "bin" sub-directory to your LIBPATH environment setting on PowerWeb startup.
PowerWeb automatically associates files within the bin directory as compiled DLL extensions. This is set up through the URL Alias Editor. If you create sub-directories under this directory, they will also be recognised as compiled DLL extension directories.
You can create further directories in other locations by simply defining an alias to that directory and giving it an object type of "API Script". Remember to include that directory on your LIBPATH.
Perform Access Control via the Remote User's IP Address: This particular example limits access to a single IP address. It is obviously easier to set up a security rule in the configuration to provide this type of protection, but the example shows the basic components of writing an API Extension. long AccessControlHook(void *parcel) { char ip[32]; ServerReadText(parcel, "Connect:/RemoteAddress", ip, sizeof(ip)); if (strcmp(ip, "12.34.56.78") != 0) { ServerWriteInteger(parcel, "Request:/StatusCode", 403); return HOOK_ERROR; } return HOOK_OK; } Guided Tour Sample Code: The Guided Tour has a set of complete examples(view the source code) of API hooks for forms processing, dynamic document translation, simple direct-call hooks, and a tree view of your server settings.
long AccessControlHook(void *parcel) { char ip[32]; ServerReadText(parcel, "Connect:/RemoteAddress", ip, sizeof(ip)); if (strcmp(ip, "12.34.56.78") != 0) { ServerWriteInteger(parcel, "Request:/StatusCode", 403); return HOOK_ERROR; } return HOOK_OK; }
The PowerWeb Server++ C/C++ Interface Function Definitions Are:
ReturnValueFunctionNameFunctionParameters long ServerGetConfig (void* parcel, void** handle); long ServerGetServer (void* parcel, void** handle); long ServerGetConnect (void* parcel, void** handle); long ServerGetRequest (void* parcel, void** handle); long ServerGetParameters (void* parcel, void** handle); long ServerGetArguments (void* parcel, void** handle); long ServerFind (void* parent, const char* pszName, void** item); long ServerKind (void* handle, unsigned long* type); long ServerSize (void* handle, unsigned long* size); long ServerName (void* handle, char* value, unsigned long size); long ServerFlush (void* handle); long ServerReadInteger (void* parent, const char* pszName, long* value); long ServerReadFloat (void* parent, const char* pszName, double* value); long ServerReadText (void* parent, const char* pszName, char* value, unsigned long size); long ServerReadBinary (void* parent, const char* pszName, unsigned char* value, unsigned long size); long ServerWriteInteger (void* parent, const char* pszName, long value); long ServerWriteFloat (void* parent, const char* pszName, double value); long ServerWriteText (void* parent, const char* pszName, const char* value); long ServerWriteBinary (void* parent, const char* pszName, const unsigned char* value, unsigned long size); long ServerAppendText (void* parent, const char* pszName, const char* value); long ServerAppendBinary (void* parent, const char* pszName, const unsigned char* value, unsigned long size); long ServerNewInteger (void* parent, const char* pszName, long value); long ServerNewFloat (void* parent, const char* pszName, double value); long ServerNewText (void* parent, const char* pszName, const char* value); long ServerNewBinary (void* parent, const char* pszName, const unsigned char* value, unsigned long size); long ServerNewList (void* parent, const char* pszName); long ServerNewSemaphore (void* parent, const char* pszName); long ServerParent (void* here, void** handle); long ServerChild (void* here, void** handle); long ServerSibling (void* here, void** handle); - ServerInterpret (void* parcel, const char* code);
Parameters:
void* parcel The parcel pointer is the same one that was passed to the API hook from PowerWeb Server++. It should be treated as a "magic cookie" which identifies the current context. The parcel is unique within the system, and allows for easy and safe multi-threading. void** handle The handle pointer is another "magic cookie", this time one that refers to a specific PowerWeb variable directory or individual variable. It is used to query a specific variable or to navigate through the hierarchy. It is a pointer to a pointer to allow PowerWeb to write the value of the handle pointer into it. void* parent The parent pointer is either the "parcel" pointer or a "handle" pointer. When the pszName contains a fully qualified global name (ie. has a prefix of "Request:/", "Server:/", etc) then the "parent" pointer is the "parcel" pointer, otherwise the pszName is a relative reference to a "handle" pointer.
void** handle The handle pointer is another "magic cookie", this time one that refers to a specific PowerWeb variable directory or individual variable. It is used to query a specific variable or to navigate through the hierarchy. It is a pointer to a pointer to allow PowerWeb to write the value of the handle pointer into it.
void* parent The parent pointer is either the "parcel" pointer or a "handle" pointer. When the pszName contains a fully qualified global name (ie. has a prefix of "Request:/", "Server:/", etc) then the "parent" pointer is the "parcel" pointer, otherwise the pszName is a relative reference to a "handle" pointer.
comp.lang.c comp.lang.c++ comp.lang.c++.leda comp.lang.c++.moderated comp.lang.cobol comp.lang.fortran