|
![]() |
![]() |
version 2003
PA_NewProcess (procPtr; stackSize; pName) → long
Parameter | Type | Description | |
procPtr | void * | → | External process code |
stackSize | long | → | Process stack size |
pName | char * | → | Process name |
Function result | long | ← | Launched process number |
Description
The routine
PA_NewProcess
creates a new process and runs the code referenced by
procPtr
(a project routine). The process will have the stack size
stackSize
and the name
pName
(usual convention applies: if the name starts with "$", the process is local).
procPtr parameter
This is the name of the plug-in routine that runs the external process. It has no parameters and returns no value and is declared as :
void MyExternalProcess (void);
See below for more details on this routine.
stackSize parameter
Pass the stack size (expressed in bytes) that 4D should allocate for the process. A minimum of 16K is advised, 32K is average. A larger stack size may be necessary depending upon the nature of the external process.
NOTE
:The 4D Plug-in can optionally use a negative stack size.
If so, it indicates to 4th Dimension that the process cannot be aborted by using the 4th Dimension Abort command from the Process menu in the Design environment.
pName parameter
Pass the name of the process in
pName
(C or Pascal string, depending on default settings or previous calls to
PA_UsePStrings
or
PA_UseCStrings
).
Returned value
If the external process is successfully started, its process number is returned. If the process could not be started 0 (zero) is returned and the appropriate error code (e.g.
eER_NotEnoughMemory
) is returned in
PA_GetLastError
.
The external process code
While writing an external process, the following actions MUST be performed:
· The entry point routine of the process code has no parameters.
· At the very beginning of the code,
PA_YieldAbsolute
MUST be called. This allows the 4D scheduler to correctly handle the addition of the external process to its internal process table.
· If, as it should be, the external process includes a waiting loop :
it must call
PA_WaitNextEvent
to get the current event returned (such as
mouseDown
). Under Macintosh, it can instead use
GetNextEvent
, but for multi-platform purpose it is recommended to use
PA_WaitNextEvent
.
|
|
it must call
PA_IsProcessDying
to see if the user or 4th Dimension wants the process to abort. If
PA_IsProcessDying
returns 1, the external process must exit the event loop as soon as possible call
PA_KillProcess
.
|
|
Executing external processes receives 1 in
PA_IsProcessDying
when:
|
· The user chooses Quit , New Database , or Open Database from the 4D File menu
· The 4D command
QUIT
4D is called,
· The routine
PA_Quit
is called.
· The user chooses Abort in the Runtime Explorer
The 4D scheduler takes control and tells the external processes it must terminate. It waits for a predetermined period of time and then authoritatively aborts any remaining executing processes . It is at this point that 4D will call the
kDeInitPackage
or
kServerDeInitPackage
phase of the 4D plug-in packages.
· Calling
PA_KillProcess
MUST be the last action performed by an external process which is terminating. This assures that the 4D scheduler is notified of the termination and updates its internal process table according.
· The 4D plug-in should NOT call any API's routine that would trigger the execution of a 4D command that displays a 4D Form from within the external process, such as
ADD RECORD, DISPLAY RECORD, DISPLAY SELECTION, MODIFY SELECTION
and
DIALOG
. Executing one of these 4th Dimension commands from within the external process will lead to a System Error.
· If the 4D plug-in external process has user interface components it may open as many windows as is required. These windows belong to the 4D plug-in's external process and form the external processes' window list. For the cases where user interfaces components are required it is the responsibility of the 4D plug-in to set up its own menu bars. 4th Dimension automatically inserts the Apple (MacOS) or Help (Windows) menus.
The 4D plug-in external process can be made invisible. For example, another process applying the 4D command
HIDE PROCESS
to the 4D plug-in process is valid. In such cases the visible field of the 4D plug-in window records are set to FALSE.
Of course, there are some differences between Mac and Windows windows.
If the programmer uses Macintosh routines and Altura Mac2Win to run its code under Windows, he can write its code "as usual" : the plug-in creates its windows, and processes them into an event loop.
A Windows programmer can create and use windows and their WinProc, as usual, 4th Dimension will give the correct event to winProc of the window that receive it. But remember that, as the windows were created from an external process and belongs to it and not to 4th Dimension, this process must run the event loop that calls
PA_WaitNextEvent
and
PA_IsProcessDying
to keep a "reference" to the code that created the windows. There is no problem in adding a winProc to the window by calling the Windows routine
SetWindowLong
.
Under MacOS, most of the Windows Manager routines are patched by 4th Dimension. In order to comply with the 4D multitasking environment the 4D plug-in must use them rather than directly accessing data structures or System Globals. For instance the MacOS toolbox function call FrontWindow will return the front most window WITHIN the 4D plug-in's external process. Meanwhile, the System Global WindowList ($9D6) will contain a pointer to the front most window for the entire 4th Dimension active session.
In both cases, the programmer can use
PA_NewWindow
to create the window on both platform and insure that it will be added to the 4th Dimension application windows list.
Example
Sample code of an external process. This is the skeleton of what should be done by every external process :
Code of the external process, using Pascal strings in this sample:
void SampleProcess()
{
char done = 0;
PA_Event event;
// tell the scheduler that we exist
PA_YieldAbsolute();
// the main event loop of this external process
while ( ! done )
{
// Should we quit the process ?
done = PA_IsProcessDying();
// Is there something for me ?
if ( ! done && PA_WaitNextEvent( &event ) )
{
// Yes. Dispatch what.
switch ( event.fWhat )
{
/* . . . we could set done to 1 here . . . */
}
}
}
PA_KillProcess();
}
Launch the external process MyExternalProcess with a stack of 32Ko.
PA_NewProcess(MyExternalProcess, (32 * 1024), "Plug-in External Process");
Code of the external process, using Pascal strings in this sample:
void Process(void)
{
#define kTopLefT 50
#define kBottomRight 300
#define kStringX 100
#define kStringY 100
#define kWinMax 32767
char index;
char done,
message[63];
PA_WindowRef aWindow;
PA_Rect bounds;
PA_Event event;
PA_YieldAbsolute();
done = (char) 0;
*message = (char) 0;
bounds.lefT = bounds.top = kTopLefT;
bounds.right = bounds.bottom = kBottomRight;
aWindow = PA_NewWindow(bounds, eWL_Window, docWindow, "\pNew plug-in document", 1);
while(!done)
{
if(PA_IsProcessDying())
{
DisposeWindow(aWindow);
done = true;
}
else
{
PA_WaitNextEvent(&event);
switch(event.what)
{
case kTerminateProcess:
DisposeWindow(aWindow);
done = true;
break;
case updateEvt:
HandleUpdateEvent(&event, aWindow, message);
break;
case mouseDown:
HandleMouseDownEvent(&event, aWindow, message);
break;
}
}
}
PA_KillProcess();
}
See Also
External processes , PA_KillProcess , PA_YieldAbsolute .
Error Handling
Use
PA_GetLastError
to see if an error occurred.