3. Questions about UniScript

3.1. I have edited one of the UniScript Files. The next time I started UniPlot the changes were gone. Why ?

During startup of UniPlot loads a library that contains all standard UniScript functions. The library has the name rs_sl.icl and is located in the \UniPlot\Program directory. After you have changed and translated (command UniScript=>Save/Execute) any standard UniScript function in the script directory you need to rebuild the library. To do so choose Tools=>Create UniScript Library.

3.2. How can I create a simple dialog box?

The following example uses the function DialogBox to create a dialog box with two text fields.

The user input will be saved with the WriteProfileString function. When the My_GetEngineData function is called, the last input is used to initialize the dialog box.

def My_GetEngineData()
{
    ssEngineType = GetProfileString("Enginedata", "Type");
    ssEngineNo = GetProfileString("Enginedata", "No");
    ssTemplate = ["Engine Type: |              |",...
                  "Engien No:   |              |"]
    svRet=DialogBox(ssTemplate,[ssEngineType, ssEngineNo], "Engine Data");
    if (svRet[1] == "DLG_CANCEL") {
        return "DLG_CANCEL";
    }
    WriteProfileString("Enginedata", "Type", svRet[1]);
    WriteProfileString("Enginedata", "No", svRet[2]);
    return svRet;
}

The following example shows how you can use the function in your program:

svEngineData = My_GetEngineData();
if (svEngineData[1] != "DLG_CANCEL") { // Was the Cancel button selected ?
    auto_ReplaceText("$EngineType$", svEngineData[1]);
    auto_ReplaceText("$EngienNo$", svEngineData[2]);
}

3.3. The UniScript function system doesn’t work perfectly, how can I execute a command ?

The UniScript function system returns immediately. The following function waits until the process is finished. The function uses the system functions CreateProcessA, WaitForSingleObject and CloseHandle from the Windows DLL kernel32.dll:

def System(ssCommand)
{
    RegisterFunction("kernel32.dll", "CreateProcessA", "int", "CreateProcessA", ..
        ["int", "char*", "int", "int", "int", "int", "int", "int", "int*", "int*"])
    RegisterFunction("kernel32.dll", "WaitForSingleObject", "int", "WaitForSingleObject", ..
        ["int", "int"])
    RegisterFunction("kernel32.dll", "CloseHandle", "int", "CloseHandle", "int")
    start = zeros(17,1)
    process_info = zeros(4,1)
    if (!CreateProcessA(0, ssCommand, 0, 0, 1, 0x08000000|32, 0, 0, start, process_info)) {
        return FALSE;
    }
    while (WaitForSingleObject(process_info[1], 100)) {
        ;
    }
    CloseHandle(process_info[1]);
    CloseHandle(process_info[2]);
    return TRUE;
}

3.4. How can I write a DLL and call one of the DLL functions from UniScript?

The following is a simple C function which checks if an array of numbers is sorted increasingly.

// monoton.c
// checks if p is increasing: p0 <= p1 <= .. <= pn
int monoton(double *p, int n)
{
    int i, n1;

    n1 = n-1;
    for (i = 0; i < n1; i++) {
        if (p[i+1] <= p[i]) {
            return 0;
        }
    }
    return 1;
}

If you use the Microsoft-C Compiler to create the DLL (Dynamic Link Library) you also need a Linker Definition File:

.. code-block:: none
LIBRARY monoton EXPORTS monoton @1

With the Microsoft-C Compiler you are now ready to create the DLL monoton.dll. With other compilers this could look a little bit different.

CL /LD monoton.c monoton.def

Note:

1.) If the file is a C++ file the functions must be declared as extern "C".

Example:

extern "C" int monoton(double *p, int n);

2.) Instead of a linker definition file (*.def) the functions can be declared as following:

extern "C" __declspec(dllexport) int monoton(double *p, int n);

Now we are ready to test the new function. First we need to register it with the help of RegisterFunction. Some C-Compilers add an underscore to the function name. In this case call RegisterFunction with the following second parameter "_monoton".

// monoton.ic
nRet = RegisterFunction("monoton.dll", "monoton", ..
                        "int", "monoton", ["double *p", "int n"])
if (nRet <= 0) MessageBox(sprintf("Error: %d", nRet));
// sichere Hülle
def IsMonoton(v)
{
    if (isreal(v) == FALSE) {
        error("need a real vector");
    }
    return monoton(v, len(v));
}
// Example: Copy the following lines into the command window:
IsMonoton(1)
IsMonoton([1,2,3,8])
IsMonoton([1,2,3,2])
tic();IsMonoton(1:100000); toc()

Another example:

// compile: cl /LD test.cpp user32.lib

#include <windows.h>

extern "C" __declspec( dllexport ) int ShowMessage(char *psMsg);

__declspec (dllexport) int ShowMessage(char *psMsg)
{
    MessageBox(NULL, psMsg, "UniPlot", MB_OK);
    return 0;
}

3.5. UniPlot online documentation contains UniScript example scripts. How can I run these scripts ?

If for example the script contains only a single line,

MessageBox("Hello");

copy the line into the UniScript command window. To do so select the text line you want to copy. Click the right mouse key and choose copy.

In the UniPlot command window, which you can open by clicking the Command button, choose the hot key Shift+Ins and type ENTER to execute the command.

If the UniScript example consists of multiple commands like the following example

x = linspace(1, 2*PI)
y = sin(x)
plot(x,y)

copy the text into a UniPlot editor. To create a new editor window, choose File=>New and select the Program Editor item.

Press the Shift+Ins key to insert the text from the clipboard. To run the script choose UniScript=>Save/Execute and in the message box that appears, click the Yes button to save the file to your hard drive.

3.6. Can I start UniPlot with command-line arguments?

Use the command line switch: /ini

With this key you can pass an IC file name to UniPlot during startup.

A command line could look like the following:

c:\Program Files\UniPlot\program\uniplot.exe /ini test.ic

The file test.ic could look like this:

// First start the standard UniPlot startup file (important!):
load(GetRootDirectory() + "startup/startup.ic");
// Now you can do what ever you like, example:
MessageBox("This is a test");
x = linspace(1, 2*PI, 500);
y = sin(x);
plot(x, y);
MessageBox("Now UniPlot will exit.");
AppQuit();

id-1874822