Compiled .PRG scripts, F.A.Q.

Q1: What are compiled .PRG scripts?

These are standard Xbase++ PRG files that are placed within a Xb2.NET web server's HTTP folder (www_root) and are dynamically compiled into a DLL when accessed by a web client. If the PRG script is modified, the DLL is automatically recompiled and the new code is loaded into server memory (with no user intervention). This feature was introduced in Xb2.NET v3.5.

Q2: What are the benefits?

Q3: Do the script files need to be placed in a special folder?

No, the PRG files (or compiled DLLs) can be placed anywhere inside the web server's WWW root folder. In addition, it is possible to have multiple script files with the same name but in different sub-directories and each serving different content, example: http://mysite.com/sales/contact.prg
http://mysite.com/support/contact.prg

Q4: What if I don't want to put source code on a production server?

No problem. There are good reasons to avoid putting source code on a production HTTP server. Here are the options based on where the development and testing is done:

Q5: What additional components need to be installed on a server to make it work?

That depends on whether PRG scripts will be dynamically compiled on the server or if pre-compiled DLLs will be simply copied into the server's HTTP folder.

Q6: Does the entire Xbase++ development environment need to be installed on the server?

There is no need to install the entire development environment. Just copy the contents from the .\XPPW32\ BIN, LIB and INCLUDE folders into the Xb2.NET HTTP server application folder (in fact, the list of files to be copied can be further reduced because they are not all needed for compiling, eg: xppfd.exe, xppdbg.exe,...).

Q7: How do I call my PRG script from a web browser?

The rule is that the main procedure in the script file must have the same name as the PRG file itself. For example, assuming that the PRG file name = "TEST_123.PRG", then the script file must contain a procedure with the name "TEST_123":

File name: "TEST_123.PRG"

STATIC nCount := 0

// this is the main procedure (procedure name = file name)
PROCEDURE TEST_123()
  ++nCount
  ThreadObject():HTTPResponse:Content := "<html><body>This is a test</body></html>"
  Return

// returns number of times main procedure was called
PROCEDURE GetCount()
  ThreadObject():HTTPResponse:Content := "<html><body>Count=" + str(nCount) + "</body></html>"
  Return

If the script file (or compiled DLL) is placed in the .\www_root\ folder of mysite.com, then the following URL will execute the desired function: http://mysite.com/test_123.prg

If the script file is placed in the .\www_root\forum\sales\ folder of mysite.com, then the following URL will execute the desired function: http://mysite.com/forum/sales/test_123.prg

Q8: Can I have multiple functions / procedures inside the script file?

Yes, one script file may contain many functions or procedures, however before any of these can be executed the main procedure must be called first (the procedure with the same name as the file itself - see Q7). The first call will compile the script and/or load the DLL into memory. Once the DLL is loaded, any function/procedure without the STATIC attribute can be executed from a web client.

Using the TEST_123.PRG example from Q7, to call the function GetCount from a browser, use one of the following URLs: http://mysite.com/GetCount()
http://mysite.com/forum/sales/GetCount()

Alternatively, the parenthesis in the above URLs may be replaced with a question mark ?, eg: http://mysite.com/GetCount?
http://mysite.com/forum/sales/GetCount?

Q9: How do I call a function in the main .exe from a script?

Use one of the following options:

Q10: What is the cause of this: "error ALK2102: unresolved external symbol"?

The Xbase++ linker (ALINK) is unable to locate a function/procedure referenced within the PRG script. If the referenced symbol is part of the Xb2.NET library, then simply add the following line at the top of the prg file: #pragma library("xb2net.lib") If the symbol is found within the main executable, then see Q9 above.

Q11: What happens to "STATIC" variables when a script is modified?

When a PRG script is modified, the following actions take place:

  1. The old DLL is unloaded. Unloading the DLL will free Xbase++ memory allocated by the DLL process (this means that STATIC variables will loose their stored values). Please note that this will only free Xbase++ memory. Resources allocated outside of the Xbase++ environment (eg. external library), will need to be explicitly freed! Use an EXIT PROCEDURE to do this like in the WebShop Checkout sample.
  2. The modified PRG script is compiled into a DLL.
  3. The new DLL is loaded into memory and the main procedure is executed.
In order to maintain state persistence during these transitions, it is necessary to include some code in the script to save its state during a DLL unload (or program termination) and to restore the previous state during DLL load. Fortunately, this is fairly easy to do using Xbase++ INIT and EXIT PROCEDURES. See State Persistence sample.



Xb2.NET homepage