INtime SDK Help
INtimeDotNet
INtime SDK v7.2 > 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.

INtimeDotNet is built as two distinct assemblies: a legacy build for .NET Framework 4.x, and a modern build shared by .NET 8 and .NET 10. The main body of this topic describes the Framework 4.x build, which most existing INtimeDotNet code targets. Where the modern .NET build differs — namespace, constructor visibility, and several parameter types — see Appendix A: .NET Framework 4.x vs. .NET 8 / .NET 10 Differences at the end of this topic.

Type Aliases

INtimeDotNet defines a small set of aliases near the top of the header that map NTX C types onto CLR primitives. These names recur throughout the constants, structures, and functions described below.

Alias Underlying CLR Type Meaning
NTXSTATUS Int16 NTX status / error code
NTXHANDLE Int32 Handle to an NTX object
RTHANDLE Int16 Native INtime (real-time) handle
NTXLOCATION Int32 RT node / location identifier
QWORD unsigned long long 64-bit unsigned
DWORD unsigned int 32-bit unsigned
WORD unsigned short 16-bit unsigned
BYTE unsigned char 8-bit unsigned
UINTPTR QWORD on _WIN64, else DWORD Pointer-sized unsigned
LPTSTR / LPCTSTR TCHAR* / const TCHAR* Native string buffer

TCHAR is wchar_t under UNICODE, otherwise char.

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 ref class INtimeException : public System::Exception

Fields

Member Type Description
status NTXSTATUS The NTX error code that caused the exception.
ntxLastErrorMessage String^ Optional last-error text from the driver.

Constructors

Signature Purpose
INtimeException(NTXSTATUS s) Status only.
INtimeException(NTXSTATUS s, Exception^ inner) Status + inner exception.
INtimeException(NTXSTATUS s, String^ eMessage) Status + message.
INtimeException(NTXSTATUS s, String^ eMessage, String^ lastError) Status + message + driver last-error text.
INtimeException(NTXSTATUS s, String^ eMessage, Exception^ inner) Status + message + inner exception.

Methods

virtual String^ ToString() override;
// Returns: "Exception {status:X} - Message : {Message}"

The Exception class includes very detailed information regarding the exception's location.

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'
}

The examples above target the Framework 4.x build. In the modern .NET 8 / .NET 10 build, ntxSendRtData4Bytes takes a wider source value (UInt64 instead of Int32) — see Appendix A.

Unavailable functions

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

Structures

INtimeDotNet defines the following structures as CLR value types (value struct); identical in both the Framework 4.x and modern .NET builds.

NTXPROCATTRIBS — process pool/segment attributes (signed). Passed into ntxCreateRtProcess to overrule process creation defaults.

Field Type
dwPoolMin Int32
dwPoolMax Int32
dwVsegSize Int32
dwObjDirSize Int32

NTXPROCATTRIBSEX — extended process attributes (unsigned, plus init wait).

Field Type
dwPoolMin, dwPoolMax, dwVsegSize, dwObjDirSize, dwWaitForInit DWORD

NTXEVENTINFO — event notification payload. Returns notifications about system state, sponsor processes, and dependent processes.

Field Type Meaning
dwNotifyType Int32 One of the event codes listed under Constants.
hClient NTXLOCATION Originating location.
dwProcessId NTXHANDLE Process involved.

NTXQUEUEINFO — queue state (see ntxGetRtQueueInfo, under Queue API).

Field Type
location NTXLOCATION
MaxShortMsgSize DWORD
QueueSize DWORD
SpaceLeft DWORD

MSG_DESCRIPTOR — long-message descriptor (see ntxGetRtLongDataMessage, ntxGetMessageDescriptor, ntxCancelRtLongDataMessage, under Queue API).

Field Type
location DWORD
msgid DWORD
request WORD
request_reply WORD
dwUserParam DWORD
length DWORD
data DWORD
reserved, reserved2 DWORD

NTXLOCATIONINFO (see ntxGetLocationInfo).

Field Type
LocationName String^
ClassName String^

NTXNODEINFO (see ntxGetRtNodeInfo).

Field Type
hLocation NTXLOCATION
nodeName String^
nodeId, nodeClass, nodeSubClass, netIdType BYTE
netId array<Byte>^

NTXNODEINFOEX — same as NTXNODEINFO except netId is BYTE^.

The matching ntxGetRtNodeInfoEx function is declared in the header but commented out, so it is not currently callable. Treat NTXNODEINFOEX as reference-only until that function is confirmed active.

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);

The guidance above applies to the Framework 4.x build. In the modern .NET 8 / .NET 10 build, these types live under an INtimeDotNet namespace instead — see Appendix A.

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_NOT_CONFIGURED
E_SLOT
E_VMEM
E_CANCELLED
E_NO_LOCAL_BUFFER
E_NTX_INTERNAL_ERROR
E_NTX_COMM_FAILURE
E_NTX_KERNEL_FAILURE
E_NTX_DSM_INTERNAL_ERROR
E_TYPE
E_PARAM
E_BAD_CALL
E_PROTECTION
E_BAD_ADDR
E_STRING
E_PROTOCOL
E_PORT_ID_USED
E_NUC_BAD_BUF
E_SEND_NOT_COMPLETE
E_ALIGNMENT
E_LOCATION
Deprecated exception codes, retained for source compatibility only (all collapse to the single value E_NOT_AN_NTX_ERROR) E_INTERRUPT_SATURATION
E_INTERRUPT_OVERFLOW
E_DATA_CHAIN
E_ZERO_DIVIDE
E_OVERFLOW
E_ARRAY_BOUNDS
E_NDP_ERROR
E_ILLEGAL_OPCODE
E_EMULATOR_TRAP
E_CHECK_EXCEPTION
E_NOT_PRESENT
E_CPU_XFER_DATA_LIMIT
E_TRANSMISSION
Error / handle sentinels NTX_ERROR
NTX_BAD_SIZE
NTX_BAD_NTXSTATUS
NTX_BAD_NTXHANDLE
NTX_UNKNOWN_ERROR_CODE_MESSAGE
NTX_ALL_LOCAL_LOCATIONS
Memory-mapping options NTX_MAP_WRITE NTX_MAP_UNALIGNED
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_REFOBJ
NTX_TYPE_ALARM
NTX_TYPE_EXTENSION
NTX_TYPE_PORT
NTX_TYPE_POOL
NTX_TYPE_HEAP
NTX_TYPE_SERVICE
NTX_TYPE_FILE
NTX_TYPE_QUEUE
NTX_TYPE_RSL_OBJECT
NTX_TYPE_RSL_REFERENCE
Flags for ntxCreateRtProcess NTX_PROC_DEBUG
NTX_PROC_EXECUTABLE_DS
NTX_PROC_SHOW_PROGRESS
NTX_PROC_WAIT_FOR_INIT
NTX_PROC_WAIT_FOR_INIT_PARAM
NTX_PROC_PIPE
NTX_PROC_STRICTRSL
NTX_PROC_SUSPEND
NTX_PROC_XM
NTX_PROC_NOTXM
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
I/O service wait flags NTX_WAIT_FOR_IOPROXY NTX_WAIT_FOR_IOSERVICE
Node / location classification NTX_LOCAL_NODE
NTX_REMOTE_NODE
NTX_SHARED_NODE
NTX_DEDICATED_NODE
NTX_NODE_SUBCLASS_SHARED
NTX_NODE_SUBCLASS_DEDICATED
NTX_NODE_SUBCLASS_UNKNOWN
NTX_NODE_SUBCLASS_PRIMARY
NTX_NODE_SUBCLASS_SECONDARY
NTX_NETID_TYPE_NONE
NTX_NETID_TYPE_MAC
NTX_NETID_TYPE_IP4
NTX_NETID_TYPE_IP6
NTX_REMOTE_GOBSNET
Sponsor-search modes NTX_START_SEARCH
NTX_CONTINUE_SEARCH
NTX_THIS_LOCATION
NTX_SPECIFIC_LOCATION
Miscellaneous constants NTX_NULL_NTXHANDLE
NTX_LOCAL
TERMINATE
NTX_UNDEFINED_LOCATION
NTX_INFINITE
NTX_NO_WAIT

NTX_INFINITE and NTX_NO_WAIT are declared as a signed Int32 in the Framework 4.x build, but as an unsigned DWORD in the modern .NET 8 / .NET 10 build. Pass INtime.NTX_INFINITE / INtime.NTX_NO_WAIT rather than the literal -1 / 0 to stay build-agnostic. See Appendix A.

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
Terminate an RT process ntxTerminateRtProcess
Delete an RT process ntxDeleteRtProcess
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
Return the location of an RT object ntxGetLocationOfRtObject
Return detail information (name and class) for a location ntxGetLocationInfo
Return node information for a location ntxGetRtNodeInfo
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 (or ntxRegisterDependencyEx, which also takes a location)
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 (or ntxUnregisterDependencyEx, which also takes a location)
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
Locate a sponsor using one of the sponsor-search modes ntxFindSponsor
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
Wait for an I/O service or I/O proxy ntxWaitForIoService
Write to a Byte array or an INtime shared memory object ntxWriteRtXxx
Return descriptive text for the last driver error ntxGetLastRtError
Return the INtime version as a single number ntxGetINtimeVersionNumber
Return the INtime product and update version strings ntxGetINtimeVersion
Pass into ntxCreateRtProcess to overrule process creation defaults NTXPROCATTRIBS
Returns notifications about system state, sponsor processes, and dependent processes NTXEVENTINFO

Reference pages for the newly added system calls in this table (ntxTerminateRtProcess, ntxDeleteRtProcess, ntxGetLocationOfRtObject, ntxGetLocationInfo, ntxGetRtNodeInfo, ntxRegisterDependencyEx, ntxUnregisterDependencyEx, ntxFindSponsor, ntxWaitForIoService, ntxGetLastRtErrorDescription, ntxGetINtimeVersionNumber, ntxGetINtimeVersion) have not been confirmed to exist yet in this help system, so they are listed here as plain text rather than links. Link them once their individual pages are published.

Queue API

INtimeDotNet includes a set of queue functions and structures, added in 2014. These use bool return values (true on success) rather than the throw-on-error pattern used elsewhere in INtimeDotNet. Their parameters are DWORD in both the Framework 4.x and modern .NET builds, so this API is not affected by the Framework / .NET 8-10 signed/unsigned differences described in Appendix A.

Function Purpose
ntxCreateRtQueue(NTXLOCATION hLoc, DWORD queueSize, DWORD msgThreshold, DWORD flags) Create an RT queue.
ntxDeleteRtQueue(NTXHANDLE hQueue) Delete an RT queue.
ntxFlushRtQueue(NTXHANDLE hQueue) Flush an RT queue.
ntxGetRtQueueInfo(NTXHANDLE hQueue, NTXQUEUEINFO% pQueueInfo) Get queue state.
ntxLookupRtQueueHandle(NTXLOCATION hLoc, String^ QueueName, DWORD dwMilliseconds) Look up a queue handle by name.
ntxCatalogRtQueueHandle(NTXHANDLE hQueue, String^ queueName) Catalog a queue handle under a name.
ntxUncatalogRtQueueHandle(NTXHANDLE hQueue, String^ queueName) Remove a queue's cataloged name.
ntxSendRtShortDataMessage(NTXHANDLE hQueue, array<Byte>^ msg, DWORD msgLength) Send a short message.
ntxReceiveRtDataMessage(NTXHANDLE hQueue, array<Byte>^ msgBuffer, DWORD msgBufferSize, DWORD dwMilliseconds, DWORD% pMsgSize) Receive a short message.
ntxSendRtLongDataMessage(NTXHANDLE hQueue, array<Byte>^ msg, DWORD msgLength, DWORD dwMilliseconds) Send a long message.
ntxGetRtLongDataMessage(NTXHANDLE hQueue, MSG_DESCRIPTOR% msgDesc, array<Byte>^ msgBuffer, DWORD msgBufferLength, DWORD% msgSize) Receive a long message.
ntxCancelRtLongDataMessage(NTXHANDLE hQueue, MSG_DESCRIPTOR% msgDesc) Cancel a pending long message.
ntxGetMessageDescriptor(MSG_DESCRIPTOR% desc, array<Byte>^ msgBuffer, DWORD msgBufferSize) Extract a message descriptor from a buffer.

No Visual Basic or Visual C# worked example is available for the Queue API in the source material this topic was built from, so none is included here. If you would like one added, provide (or request drafting of) a sample usage and it can be inserted here in the same style as the Example Code section above.

Appendix A: .NET Framework 4.x vs. .NET 8 / .NET 10 Differences

INtimeDotNet compiles into two distinct assemblies, selected by the DOTNET452 preprocessor symbol:

Build DOTNET452 Namespace Notes
.NET Framework 4.x Not defined (global / none) Legacy build. Types live in the global namespace. This is the build assumed throughout the main body of this topic.
Modern .NET (.NET 8 / .NET 10) Defined INtimeDotNet The #else branch. The same branch is used for any non-Framework target, so .NET 8 and .NET 10 share identical surface area — there are no source differences between them.

A.1 Namespacing

// Modern .NET 8/10 only:
namespace INtimeDotNet {
    // INtimeException, INtime ...
}

In Framework builds there is no enclosing namespace, so fully-qualified names differ:

Type Framework 4.x .NET 8 / .NET 10
Exception INtimeException INtimeDotNet.INtimeException
Main class INtime INtimeDotNet.INtime

A.2 INtime Class Constructor Visibility

Build Declaration Effect
Framework 4.x private: INtime(){} Cannot be instantiated; use static members only.
.NET 8 / .NET 10 public: INtime(){} Public default constructor exists (still effectively a static-only class).

A.3 Constant Declaration Kind

In Framework builds, constants are declared with literal (compile-time) values. In modern .NET they are declared as static initonly (read-only static fields). The values themselves are identical — only the declaration kind, and in a few cases the field type (see A.4), differ.

A.4 Signed vs. Unsigned Parameter/Constant Types

This is the single most common difference encountered when porting. In Framework builds, many parameters and constants are declared as signed Int32. In modern .NET, the equivalent fields are declared as the unsigned DWORD / UInt32 / UInt64.

Category Framework 4.x .NET 8/10
Wait timeouts (NTX_INFINITE, NTX_NO_WAIT) Int32 DWORD
Mailbox/queue creation flags (NTX_DATA_MAILBOX, NTX_FIFO_QUEUING, etc.) Int32 DWORD (values unchanged)
Timeout params on lookup/receive/wait functions (e.g. ntxLookupNtxhandle, ntxReceiveRtDataXxx, ntxWaitForRtProcess, ntxRegisterDependency, ntxNotifyEvent) Int32 DWORD or UInt32
Memory-offset parameters (pSrc/pDst in ntxReadRtXxx/ntxWriteRtXxx) Int32 UInt32
hObj parameter to ntxGetType Int32 NTXHANDLE

Pass INtime.NTX_INFINITE / INtime.NTX_NO_WAIT rather than literal -1 / 0, to stay build-agnostic.

A.5 ntxSendRtData4Bytes Width Change

Build lSrc parameter type
Framework 4.x Int32
.NET 8/10 UInt64

This is a breaking change if porting code that currently passes an Int32 value directly.

A.6 Queue API

The 2014 Queue API (documented above under Queue API) already used DWORD parameters in both builds, so it is unaffected by the signed/unsigned split described in A.4 and ports cleanly.

A.7 Quick Porting Checklist (Framework 4.x → .NET 8 / .NET 10)

  1. Namespace — qualify types as INtimeDotNet.INtime / INtimeDotNet.INtimeException, or add using namespace INtimeDotNet;.
  2. Timeouts & flags — were signed Int32, now unsigned DWORD/UInt32. Prefer the NTX_INFINITE/NTX_NO_WAIT constants over raw -1/0.
  3. ntxSendRtData4Bytes — the source argument widens from Int32 to UInt64.
  4. Memory-offset params (pSrc/pDst in the ntxReadRtXxx/ntxWriteRtXxx helpers) — signed Int32 → unsigned UInt32.
  5. Constructor — INtime now has a public default constructor; still treat it as a static-only class.
  6. .NET 8 vs. .NET 10 — no source differences; both compile the same non-DOTNET452 branch.