INtime SDK Help
INtimeDotNet
INtime SDK v6 > About INtime > Alternate APIs > INtimeDotNet
This topic contains the following:

Overview

INtimeDotNet provides INtime NTX functions for .Net programs. Restrictions of the Common Language Runtime (CLR) versus the earlier C/C++ environment required certain modifications. INtimeDotNet requires Visual Studio 2005, or later.

With NTX (INtime's Windows API) functions, a Windows program can communicate with a real-time program running in the INtime real-time environment. NTX has evolved to support many versions of Windows.

In .Net, multiple programming languages target the same CLR and a whole framework of classes for .Net has emerged. Microsoft Visual Studio ships with CLR support for Visual Basic, C# and, in a slightly less structured way, C++ with managed extensions. Other software manufacturers offer additional programming languages.

User interface

The CLR provides:

The CLR does not provide an unsafe pointer type, and does not allow free casting from one type into another one.

Some NTX functions use untyped pointers that can even include NULL. Since the .NET framework does not accommodate this, NTX functions require a wrapper. In addition, the .NET framework uses exceptions extensively and, for various reasons, employs overloaded function definitions.

INtimeDotNet is a wrapper that integrates NTX into .Net. It is not a class framework. It matches NTX as closely as possible.

All INtimeDotNet functions are static members of the INtime class. This means you do not need to create an instance of the INtime class to access them. (In fact, this should cause a compiler error as the constructor is private.) Instead, you either qualify the function name by preceding it with INtime., or in the case of Visual Basic.Net, you may omit it if you have include an Imports INtime statement at the beginning of your program.

The next sections detail the main differences between NTX and INtimeDotNet.

Deviations from NTX

INtimeDotNet deviates from NTX in these areas:

Further, INtimeDotNet does not include all NTX functions.

Exceptions

In the traditional Windows approach, when an exception occurs in NTX (for example, an invalid argument or a timeout while waiting for en event), a dedicated value returns and the programmer must then call ntxGetLastRtError to obtain the actual exception code.

In some cases a pointer value (-1 if an exception occurred) returns. The .NET framework cannot accept such pointer values. In addition, the .NET framework uses exceptions in many places. To conform to .NET style, INtimeDotNet uses exceptions in such cases. INtimeDotNet exceptions, derived from the Exception class, add a status member variable that contains the NTX exception code:

The INtimeException class

public class INtimeException : public System::Exception
{
  INtimeException(UInt16 s) { status = s;};
  UInt16   status;
};

The Exception class includes very detailed information regarding the exception's location and also includes the ToString member function that converts the information to a String.

The following code fragments illustrate first the NTX style, then the INtimeDotNet method (using Visual Basic and Visual C#):

Exception handling in NTX

NTXHANDLE hObject;
  hObject = ntxCreateRtMailbox(hLocation, NTX_DATA_MAILBOX);
  if (NTX_BAD_NTXHANDLE == hObject) {
    status = ntxGetLastRtError();
    // further exception handling
  }
  // use hObject

Exception handling in Visual Basic

Dim hObject As UInt32
Try
  hObject = ntxCreateRtMailbox(hLocation, NTX_DATA_MAILBOX)
Catch exc As INtimeException
  status = exc.status
  ' further exception handling
End Try
' use hObject

Exception handling in Visual C#

UInt32 hObject;
try {
  hObject = INtime.ntxCreateRtMailbox(hLocation,
    INtime.NTX_DATA_MAILBOX);
}
catch (INtimeException exc) {
  status = exc.status;
  // further exception handling
}
// use hObject

As a result of the use of exceptions, the INtimeDotNet functions never return these values:

NTX_ERROR NTX_BAD_NTXHANDLE BAD_POINTER BAD_TRANSACTION_ID NTX_BAD_SIZE

Pointers

In many cases, NTX uses untyped or void pointers to refer to a buffer which contains only a series of bytes. Examples include the messages transmitted with ntxSendRtData or ntxReceiveRtData. This type of parameter is not legal in the CLR because pointers are not allowed

In standard C or C++, i.e., in NTX, a NULL can be passed as an argument to a function in lieu of a pointer to indicate that some default value should be used. Again, this is not legal in the CLR because pointers are not allowed. Instead, the following mechanism are used:

Example Code

As an example, assume you have the following (packed) structure which you are using to send and receive messages:

Sample message layout

typedef struct {
  WORD  value1;
  WORD  value2;
  DWORD value3;
  unsigned char data[8];
} MESSAGE;

The following code fragments illustrate a message built and sent with NTX, Visual Basic, and Visual C# respectively.

Sending a message with NTX

MESSAGE msg;
memset (&msg, '\0', sizeof(msg));
WORD status;
msg.value1 = 1;
msg.value2 = 4;
msg.value3 = 100;
memcpy (msg.data, "Hello", strlen("Hello"));

status = ntxSendRtData(hMbox, &msg, sizeof(msg));
if (E_OK != status) {
  // deal with exception 'status'
}

Sending a message with Visual Basic

The first options uses the different ntxSendRtData methods to send the data in the appropriate chunks. For example:

Imports INtime
Imports System.Text

Dim StrBuff() As Byte
StrBuff = Encoding.ASCII.GetBytes("Hello")
Try
  ntxSendRtData2Bytes(hMbox, CShort(1))
  ntxSendRtData2Bytes(hMbox, CShort(4))
  ntxSendRtData4Bytes(hMbox, CInt(100))
  ntxSendRtDataBytes(hMbox, StrBuff, StrBuff.Length)
Catch exc As INtimeException
  'deal with exception in exc.status
End Try

The second alternative packs the data into an array of bytes and sends it all in one call. For example:

Dim DataBuf(128) As Byte
Array.Clear(DataBuf, 0, 128);
Dim ByteBuf() As Byte
Dim DCount As Integer = 0

ByteBuf = BitConverter.GetBytes(CShort(1))
ByteBuf.CopyTo(DataBuf, DCount)
DCount = DCount + ByteBuf.Length

ByteBuf = BitConverter.GetBytes(CShort(4))
ByteBuf.CopyTo(DataBuf, DCount)
DCount = DCount + ByteBuf.Length

ByteBuf = BitConverter.GetBytes(CInt(100))
ByteBuf.CopyTo(DataBuf, DCount)
DCount = DCount + ByteBuf.Length

ByteBuf = Encoding.ASCII.GetBytes("Hello")
ByteBuf.CopyTo(DataBuf, DCount)
DCount = DCount + ByteBuf.Length
Try
  ntxSendRtDataBytes(hMbox, DataBuf, DCount)
Catch exc As INtimeException
  'deal with exception in exc.status
End Try

Sending a message with Visual C#

Again, the first option sends pieces of the data in the appropriate chunks.

byte[] ByteBuf;
ByteBuf = Encoding.ASCII.GetBytes("Hello");
try {
  INtime.ntxSendRtData2Bytes(hMbox, (Int16)1);
  INtime.ntxSendRtData2Bytes(hMbox, (Int16)4);
  INtime.ntxSendRtData4Bytes(hMbox, (Int32)100);
  INtime.ntxSendRtDataBytes(hMbox, ByteBuf, ByteBuf.Length);
}
catch (INtimeException exc) {
  // deal with exception exc.status
}

And the second option packs the data into a byte array and sends it all in one call.

const int RTBUFSIZE = 128;
byte[] DataBuf = new byte[RTBUFSIZE];
byte[] ByteBuf;
int DCount = 0;
Array.Clear(DataBuf, 0, RTBUFSIZE);

ByteBuf = BitConverter.GetBytes((Int16)(1));
ByteBuf.CopyTo(DataBuf, DCount);
DCount = DCount + ByteBuf.Length;

ByteBuf = BitConverter.GetBytes((Int16) (4));
ByteBuf.CopyTo(DataBuf, DCount);
DCount = DCount + ByteBuf.Length;

ByteBuf = BitConverter.GetBytes((Int32) (100));
ByteBuf.CopyTo(DataBuf, DCount);
DCount = DCount + ByteBuf.Length;

ByteBuf = Encoding.ASCII.GetBytes("Hello");
ByteBuf.CopyTo(DataBuf, DCount);
DCount = DCount + ByteBuf.Length;
try {
  INtime.ntxSendRtDataBytes(hMbox, DataBuf, DCount);
}
catch (INtimeException exc) {
  // deal with exception 'exc.status'
}

Unavailable functions

These NTX functions are not (directly) available in INtimeDotNet because of pointer limitations or because they have no use:

Adding INtimeDotNet to a Visual Studio project

A .NET component contains both object code and interface definitions. To use the INtimeDotNet component in a Visual Studio project, you must add a reference to the component:

  1. Select the Project / Add Reference menu item or right click the References item in the Solution Explorer.
  2. Select Add Reference. A list of known components displays.
  3. Select the "INtimeDotNet" component.
  4. Press "Select", then "OK".

Importing INtimeDotNet names in Visual Basic

In Visual Basic, you can add a statement similar to this at the start of the program to avoid fully qualifying all names:

Imports INtime

Importing INtimeDotNet names in Visual C#

In Visual C#, you must qualify all constants, exception codes, and function names with "INtime". No using or namespace statements are required. For Example:

hMbox = INtime.ntxCreateRtMailbox(hLoc, INtime.NTX_DATA_MAILBOX);

Constants

The following constants are defined for exception codes, flags, and event codes.

In Visual Basic, you can use these constants directly; in Visual C# you must qualify the name with the INtime class name.

Description Constants
Exception codes (for details see INtime Status Codes) E_OK
E_TIME
E_MEM
E_BUSY
E_LIMIT
E_CONTEXT
E_EXIST
E_STATE
E_SLOT
E_NTX_INTERNAL_ERROR
E_NTX_COMM_FAILURE
E_NTX_DSM_INTERNAL_ERROR
E_TYPE
E_PARAM
E_BAD_CALL
E_PROTECTION
E_BAD_ADDR
E_STRING
E_ALIGNMENT
E_LOCATION
Flags for creating objects NTX_DATA_MAILBOX
NTX_OBJECT_MAILBOX
NTX_PRIORITY_QUEUING
NTX_FIFO_QUEUING
CREATE_UNBOUND

(Object Mailbox Depth Flags)
NTX_DEPTH_8
NTX_DEPTH_12
NTX_DEPTH_16
NTX_DEPTH_20
NTX_DEPTH_24
NTX_DEPTH_28
NTX_DEPTH_32
NTX_DEPTH_36
NTX_DEPTH_40
NTX_DEPTH_44
NTX_DEPTH_48
NTX_DEPTH_52
NTX_DEPTH_56
NTX_DEPTH_60
NTX_DEPTH_64
Possible return values from ntxGetRtType NTX_TYPE_RT_PROCESS
NTX_TYPE_RT_THREAD
NTX_TYPE_MAILBOX
NTX_TYPE_RT_SEMAPHORE
NTX_TYPE_REGION
NTX_TYPE_RT_SHARED_MEMORY
NTX_TYPE_EXTENSION
NTX_TYPE_PORT
NTX_TYPE_POOL
NTX_TYPE_HEAP
NTX_TYPE_SERVICE
Flags for ntxCreateRtProcess NTX_PROC_DEBUG
NTX_PROC_EXECUTABLE_DS
NTX_PROC_SHOW_PROGRESS
NTX_PROC_WAIT_FOR_INIT
Flags for ntxNotifyEvent NTX_SPONSOR_NOTIFICATIONS
NTX_CLIENT_NOTIFICATIONS
NTX_DEPENDENT_NOTIFICATIONS
NTX_SYSTEM_EVENT_NOTIFICATIONS
Types returned by ntxNofityEvent DEPENDENT_REGISTERED
DEPENDENT_UNREGISTERED
DEPENDENT_TERMINATED
SPONSOR_TERMINATED
SPONSOR_UNREGISTERED
RT_CLIENT_DOWN
RT_CLIENT_UP
Miscellaneous constants NTX_NULL_NTXHANDLE
NTX_LOCAL
TERMINATE
NTX_UNDEFINED_LOCATION
NTX_INFINITE
NTX_NO_WAIT

System Calls

This lists common operations on INtimeDotNet and the system calls that perform the operations:

To . . . Use this system call . . .
Name an object in a process directory ntxCatalogNtxHandle
Create an RT mailbox ntxCreateRtMailbox
Load an RT executable and runs it in a new process ntxCreateRtProcess
Create an RT semaphore ntxCreateRtSemaphore
Delete an RT mailbox ntxDeleteRtMailbox
Delete an RT semaphore ntxDeleteRtSemaphore
Return a handle to the first known location ntxGetFirstLocation
Return a handle to the specified location ntxGetLocationByName
Return the name by which the specified location handle is known to NTX ntxGetNameOfLocation
Return the handle to the location following the one returned by the last call to ntxGetFirstLocation or ntxGetNextLocation in the current thread. ntxGetNextLocation
Obtain the root RT process handle ntxGetRootRtProcess
Return a string that contains the name of the status code passed ntxGetRtErrorName
Return a memory region's size ntxGetRtSize
Verify whether the RT kernel is successfully initialized ntxGetRtStatus
Return the type of an NTX handle ntxGetType
Obtain an NTXHANDLE that corresponds to an RTHANDLE ntxImportRtHandle
Return a short sentence (no punctuation) that describes "Status" ntxLoadRtErrorString
Search the given process's object directory for the given name and return the object handle, if found ntxLookupNtxhandle
Block until one of the desired notifications is received ntxNotifyEvent
Read from a Byte array or an INtime shared memory object ntxReadRtXxx
Wait for and then copy data out of an RT data mailbox ntxReceiveRtDataXxx
Receive handles from an object mailbox ntxReceiveRtHandle
Create a dependency relationship between the calling process and the specified sponsor ntxRegisterDependency
Register the calling process as a Sponsor with the given name ntxRegisterSponsor
Release units to an RT semaphore ntxReleaseSemaphore
Copy data to an RT data mailbox ntxSendRtDataXxx
Send an object handle to an object mailbox ntxSendRtHandle
Start an RT process previously loaded with ntxCreateRtProcess ntxStartRtProcess
Start a local INtime node ntxStartLocalRtNode
Stop a local INtime node ntxStopLocalRtNode
Remove an entry from a process' object directory ntxUncatalogNtxHandle
Remove the dependency relationship between the calling process and the specified sponsor ntxUnregisterDependency
Remove the current sponsor name from the active sponsor state. No notifications are made to dependents and the name remains in use until the sponsor is removed from all relationships ntxUnregisterSponsor
Wait for an RT process previously loaded with ntxCreateRtProcess to terminate ntxWaitForRtProcess
Request a specified number of units to be received from the RTsemaphore ntxWaitForRtSemaphore
Write to a Byte array or an INtime shared memory object ntxWriteRtXxx
Pass into ntxCreateRtProcess to overrule process creation defaults NTXPROCATTRIBS
Returns notifications about system state, sponsor processes, and dependent processes NTXEVENTINFO