Chapter 4—Omnis .NET Objects

Support for Microsoft .NET is provided in Omnis Studio using the .NET Objects external component. You should note that this component is now deprecated in Omnis Studio 10.x or above, and is currently only provided for backwards compatibility in existing Omnis Studio libraries that use .NET. You should not use the .NET Objects external component for new applications in Omnis Studio 10.x or above.

This chapter describes how you can access .NET Objects using the .NET Objects component available in some editions of Omnis Studio. It assumes that you have both a basic knowledge of Omnis Studio notation, creating Object references, and a basic knowledge of the .NET Language.

Introduction

The .NET Objects component for Omnis Studio allows you to integrate .NET functionality into your Omnis applications. You can create Omnis Objects based on .NET core functionality or third-party class libraries and call their methods in your Omnis code further extending the power and versatility of Omnis Studio. The Omnis .NET Objects component is available for the Microsoft Windows only at present.

Why use .NET

The Microsoft .NET Framework provides a library of prepackaged functionality, including base classes and various APIs, that can be reused and integrated into your Omnis applications. The base classes provide standard functionality such as input/output, string manipulation, security management, and network communications.

In addition to the base classes provided in the .NET Framework, there are thousands of class libraries available from third-party developers providing a broad range of functionality, available to Omnis developers via the .NET Objects component. These can be located in your .NET Framework folder and added into Omnis using a $addclass() method call.

Software Requirements

Omnis Studio

To use the Omnis .NET Objects component, you need Omnis Studio 4.3 or higher. The component is not supported in older versions of Omnis Studio.

Microsoft .NET Framework

In order to use the .NET Objects component in Omnis Studio, you must download and install the Microsoft .NET framework: the version of .NET framework must be appropriate for the version of Windows and Omnis Studio you are running.

See the Microsoft .NET web site for further details on system requirements for the .NET framework.

For further details about the .NET framework, for some useful tutorials, and to download the version you need, go to:

Setting up

The Omnis .NET Objects component is installed as part of the standard Development version of Omnis Studio (Windows only). The component itself is comprised of two DLLs:

  1. OMDOTNET.DLL
    The Omnis .NET Objects component is located in the root of your Omnis Studio folder (in Program Files), but must be registered with .NET; see below.

  2. OMDNOBJS.DLL
    This is an Omnis Studio external component and is located in the XCOMP folder within the Omnis Studio development tree.

Registering the component

The Omnis .NET Objects component (OMDOTNET.DLL) is installed into the root of your Omnis Studio folder, but it must be registered with .NET in order to work. If you have Admin rights this can be done from a command line prompt (DOS box) using the Regasm program and the following command:

REGASM “C:\Program Files\Omnis Software\<OS-version>\OMDOTNET.DLL”

If you have Admin rights you can run Regasm.exe from the Start>>Run command.

Regasm.exe is an application provided with the .NET Framework and you may be required to locate it, if it isn’t on your PATH. It normally resides in a folder called Microsoft.NET\Framework\<Version Number> which is held in the operating system folder C:\Windows.

You should enclose path name to the OMDOTNET.DLL file in quotes, especially if the pathname has spaces in it. For example:

C:\Windows\Microsoft.NET\Framework\<version-no>\RegAsm.exe "C:\Program Files\Omnis Software\<OS-version>\OMDOTNET.DLL"

Failure to have the Microsoft .NET Framework installed or failing to register OMDOTNET.DLL will result in an error, which will be reported in the Omnis trace log. You can open the Trace log from the Omnis Tools menu – if a component fails to load, it will be reported in the Omnis trace log.

Deployment

If you wish to deploy the Omnis .NET Objects component as part of your application, you must install both DLLs and register the OMDOTNET.DLL file on any client machine, as described above.

The .NET Example Library

There is an example library showing how the .NET Objects component works. The example library, which monitors RSS feeds from news web sites, is available under the Samples option in the HUB when you first launch Omnis (in the Studio Browser, press F2). Code from the example library is used later in this section to show you how to use the component.

Creating .NET Objects

Creating .NET Objects is a two-stage process that is similar to the process of creating Automation Objects or Java Objects in Omnis. A .NET Object is first declared and then constructed using the $createobject() method. This process is described in the following sections.

Defining .NET Objects

.NET Objects can be manipulated in a similar manner to other Omnis Objects. A .NET Object can be defined in a variety of ways:

Defining .NET Objects via the Method Editor

To create a .NET Object in the Omnis Method Editor, simply declare an Object variable (e.g. an instance variable) and set its subtype to the desired .NET Objects Class. To do this, click the Subtype dropdown menu to open the “Select Object dialog, navigate the Object Selection Tree, highlight the class your require and click OK. The Object Selection Tree is split into one or more sections under the “NET” heading. These are “mscorlib” (basic .NET objects) and any classes that you have manually loaded (using $addclass).

The following shows a .NET Object being defined from a .NET Class which resides in the SOAP module which has been loaded manually.

image1

Defining .NET Objects using Object References

Object Reference variables are a relatively new feature, introduced in Omnis Studio 4.0. Object Reference variables are similar to Object variables, but you are responsible for the allocation and de-allocation of the object concerned.

Object References are declared in the Method Editor, but do not have a subtype. To declare an Object Reference, simply declare a variable in the Method Editor and set its type to “Object Reference”. You can set a subtype in order to view the object’s methods in the Interface Manager, but the object associated with the reference has to be allocated using the $newref() method.

The following shows both the lString object variable and the lStringRef Object Reference.

image2

To allocate an Object to an Object Reference, you must use the notation. As notation strings for .NET Objects can be very long (due to the large hierarchies that are present in some .NET packages) the Notation Inspector can be displayed as a helper window when entering the notation for .NET Objects. You need to navigate the $extobjects.DNet.$objects group to find the .NET class you wish to reference. You can drag and drop the notation from the Notation Inspector to the Method Editor, and the full notation is created for you, such as the following:

image3

Omnis will enclose the object string in double forward slashes since it does not recognize it as a variable or method name All .NET Object notation begins with $root.$extobjects.DNet.$objects (although you can omit $root and $extobjects), and the remainder of the notation string is dependant on the .NET class being used. The complete notation for a String object is as follows:

$root.$extobjects.DNet.$objects.//NET\mscorlib\System\String//

Now you have to add a call to the $newref() method manually. This method is responsible for allocating an Object to the Object Reference. Therefore, the complete method to allocate the String object would be as follows:

Calculate lStringRef as DNet.$objects.//NET\mscorlib\System\String//.$newref()

When the above method is executed, a String .NET Object will be created and assigned to the Object Reference lStringRef. It is your responsibility to ensure that this Object is deleted using the $deleteref() method once it has served its purpose. To de-allocate the variable, you can use:

Do lStringRef.$deleteref()

For further information about Object References, refer to Omnis Programming manual.

Defining .NET Objects via Notation

.NET Objects can be defined using the Object type via notation. To define a .NET Object via notation, simply follow the instructions in the previous section but use an Object type variable instead of an Object Reference type and call the $new() method instead of the $newref method.

Constructing .NET Objects

Once a .NET Object has been declared, it needs to be constructed. Declaring a .NET Object simply tells Omnis that the Object exists. Constructing a .NET Object using the $createobject() method actually performs the work of constructing the Object inside the .NET Virtual Machine.

By default all .NET Objects will have at least one $createobject() method which takes no parameters. This method can be used to create a .NET Object as follows:

Do lStringRef.$createobject()

Other .NET Objects may have more than one $createobject() method. In this case, each $createobject() method corresponds directly to a .NET Constructor for the class that is being used. For example, the .NET.System.String class has the following constructors:

String(char* value)
String(char[] value)
String(sbyte* bytes)
String(char c,int count)
String(char* value,int startindex,int length)
String(char[] value,int startindex,int length)
String(sbyte* value,int startindex,int length)
String(sbyte* value,int startindex,int length, int Encoding)

These are mirrored in Omnis by the following $createobject() methods:

image4

Calling any of above $createobject() methods will invoke the corresponding Constructor in .NET and create the .NET Object in the Virtual Machine. For example, calling:

Do mystring1.$createobject(mystring)

will invoke the String(char[] value).

Subclassing .NET Objects

.NET Objects can be subclassed by creating an Object class (using the “New Empty Class” option in the Studio Browser followed by the “Object” option) and setting its “Super Class” property ($superclass) via the Property Manager and the Object Selection Tree. For example, you can create an Object class and set its $superclass property to “.DNet.NET\mscorlib\System\String” via the Select Object dialog, as follows:

image5

In this case, the oString object class becomes a subclassed object of String and inherits all of its methods as follows:

image6

Subclassed .NET Objects can be used to define Object and Object Reference variables in the same manner as .NET Objects. Defining .NET Object variables is described in the previous section.

Using .NET Objects

The following sections describe how Omnis Data Types are converted to .NET Data Types, how you can pass parameters from Omnis to .NET, how you handle Return Values, and how you can retrieve data from .NET Objects. Other topics, such as Error Handling and Cache Control, are discussed later.

Please check the Tech Notes on the Omnis web site (www.omnis.net) for supplementary information about using the .NET Objects component with complex data types.

Parameter Data Types

The following table shows how Omnis Data Types are converted to .NET Data Types when used as parameters to .NET Object methods. The Omnis Data Types marked with a ‘*’ are known as Overloaded Types as they are compatible with more than one .NET Data Type.

Omnis Type .NET Type
Simple types
Character char or char[]
Binary byte or byte[]
Number Long integer int, long or byte
Number Short integer short
Number floating dp
or Number <n> dp
float or double
Boolean boolean
Complex types
List .NET Array
Object .NET Object
Object Reference .NET Object

As you can see from the above, most of the Data Types in Omnis can be coerced into multiple .NET Data Types. Although this coercion happens automatically, it is useful to be aware of Overloaded Types as they provide you with greater flexibility when programming with .NET Objects. For example, if you wish to construct a .NET.System.Byte object, you could define a Binary variable, load the byte into the variable and then call $createobject() with this variable. However, it is much quicker to simply call $createobject() using the integer value of the byte. For example:

Do mybyte.$createobject(65) 

will create a .NET Byte object whose value is 65.

For a further explanation of Overloaded Types, see the Appendix.

Passing Parameters

In order to call .NET Objects effectively, it is necessary to know how Omnis Data Types are mapped to .NET Data Types when passing parameters. .NET Object Parameters can be categorized into two basic types:

Simple Parameter Types

Complex Parameter Types

Passing Simple Parameter Types

Passing simple parameter types is relatively easy. You can call the .NET Object method with parameter(s), as you would call any method in Omnis. In the following example, the simple parameter type lpos is passed to the .NET.System.String charAt() function. This function returns the character value ‘l’ as this character resides at index 3 of the .NET String.

image7

Passing Complex Parameter Types

Complex Parameter types such as lists and Objects can be passed to .NET, however these Parameter types must be initialised before being used.

List Types

Omnis lists must contain valid data before being passed to a .NET Object. Note that if you use a list that has more than one column, only the first column will be used. Omnis lists which do not contain valid data will cause .NET Objects to return an error. For a further explanation of error handling, see the Error Handling section.

Omnis converts Single Column Lists to .NET Arrays based on the type of the data that is stored in the list. This conversion can be described by the following table:

Omnis List .NET Array Type
Omnis List containing Number Long integer Types int[] or long[]
Omnis List containing Number floating dp Types float[] or double[]
Omnis List containing Number Short integer Types short[]
Omnis List containing Boolean Types boolean[]
Omnis List containing Object References Array of .NET Objects

As you can see from the table above, Overloaded Types are also supported by Omnis Lists. For an explanation of Overloaded Types, see the Appendix. It should also be noted that char[] and byte[] are absent from the above table. This is because .NET char[] and byte[] types are created directly from Omnis Character and Binary variables.

Omnis will always attempt to determine the type of Array that you are trying to pass as a parameter by examining the data in the List. If a list contains .NET Objects, Omnis will attempt to determine the type of the objects in the list. If the type of all the objects is found to be the same, it is assumed that you are passing a parameter of that type. For example, if you create an Omnis list of .NET.System.String Objects, Omnis will assume that you are passing a String Array Parameter to .NET. However, if any of the Objects are found to be of different types, Omnis will assume that you are passing a generic Object Array (.NET.System.Object) to .NET.

When calling .NET methods that take arrays as parameters, you should make sure that the Omnis list that you pass to the method in question contains appropriate data. Lists which do not contain appropriate data will cause the function call to fail with an error (see the Error Handling section). For example, if you create an Omnis List with 12 .NET.System.String Objects and add an extra .NET.System.Byte object by mistake, your method call will fail if you are attempting to call a .NET function that accepts a .NET.System.String Array as a parameter.

Important Note: When creating a list of .NET Objects, Object References should be used. This is because standard objects cannot be used in Omnis Lists. Once you have finished using your list of Object References, remember to delete each reference in the list by calling $deleteref for each reference. Please refer to the Omnis Programming manual for further information about Object References.

Object Types

.NET Objects should be “created” using $createobject() before being passed as parameters to other .NET Objects. Passing an uninitialized object to a .NET function will return an error.

Returning Values From .NET Methods

The following table shows how .NET Return types are converted to Omnis data types.

.NET Type Omnis Type
char[] or char Character
byte[] or byte Binary
int or long Number Long integer
float or double Number Floating dp or Number dp
short Number Short Integer
Boolean Boolean
.NET Arrays (except char[] and byte[]) List
Objects Object References

As you can see from the table above, this is merely a reversal of the Omnis to .NET table shown in the previous section.

To return a value from a .NET object method, use the Method Editor to specify the variable that will be used to hold the return value. You must ensure that the Omnis variable that you are using is of the correct type to accept the value that will be returned from .NET. If this is not the case, an error will occur and the hash variables #ERRCODE and #ERRTEXT will be set accordingly (see the Error Handling section later in this manual).

Important: If a .NET object returns a base object type, such as String, this will be returned as a base Omnis type. For example, the string object has a method called $substring which returns a character variable and not an object string. This is due to the fact that it would be otherwise impossible to get the contents of a string object if only a string object was returned.

Obtaining constant (or Enum) values

Due to the numerous .NET classes available, constants (enums) are not added to the Omnis constants as shown in the Catalog (F9). To obtain the value of a particular constant, you can call the $getenum function with the fully qualified .NET class. For example, to open an existing stream object you can call:

Do oStream.$createobject( myFile,DNet.$getenum("System.IO.FileMode.Open"))

Adding .NET Classes

Additional .NET classes can be added by calling DNET.$addclass() with the location of the filename. For example, to add SOAP classes you can execute:

Calculate #S1 as con(DNet.$basefolder(),sys(9), "System.Runtime.Serialization.Formatters.Soap.dll")
Do DNet.$addclass(#S1Returns #1

The first line of the method obtains the installation folder of the .NET framework and appends the soap filename. The second line adds the class (or classes if the string has more than one filename separated by commas) to the Omnis .NET classes which are available; the value returned is the number of files added, in this case 1. The .NET objects in the class are then available in the Select Object dialog when creating object variables.

image8

It’s not necessary to restart Omnis after adding classes, but remember that this information is not persistent between sessions, so you will need to add the classes into Omnis each time the application starts up or a window is opened.

Error Handling

.NET Objects makes full use of the #ERRCODE and #ERRTEXT variables in Omnis. If an error occurs while executing a .NET object method, these variables will report the error code and text on return from the method. #ERRCODE will produce the value 0 after a successful .NET method call.

.NET Objects example library

There is an example library showing how the .NET Objects component works. The example library, which monitors RSS feeds from news web sites, is available under the Examples link in the Welcome window when you first launch Omnis – you can open this window by clicking on the New Users button in the main Omnis toolbar.

image9

The example library has a number of pre-defined feeds from world-wide news organizations. After selecting a feed from the droplist, double-click a story headline to view the story detail. If you have Microsoft Internet Explorer ActiveX installed, this will be shown within an Omnis window, otherwise your default browser is used.

You can examine the code in the library to see how the .NET Objects component can be used in Omnis applications to access .NET functionality.

The RSS feed component

The RSS feed application comprises an Omnis library and a DLL which are located in the \welcome\examples folder under the main Omnis folder. The rssreader.dll contains the compiled C# code and provides Omnis with a single .NET object with three properties and two methods.

The first method in the RSS feed object, getdocument(), retrieves the XML source from the specified address in the rssUrl property. Thereafter it parses out the XML in the ‘channel’ node and sets it to the channelNode property. This is of type System.Xml.XmlNode and allows Omnis to call its member functions to determine title, language, and so on, of the RSS feed. Lastly it retrieves a list of all the ‘item’ or story XML nodes within the channel node itself. The property numberOfTags is derived from the number of ‘item’ nodes within the XML source.

The second method, getItemTags(), allows Omnis access to the nth story XmlNode determined by the function argument. Once again, calls to member functions can further extract XML from the XmlNode object and provide information such as Story Headline, Feed Description and Publish Date.

The RSS feed library

To discover how Omnis uses the .NET object you should examine the code in the RSS feed library. The Startup_Task in the library opens the RSS window and creates the object. The code for the $construct() method of the RSS window is as follows. The first part of the method loads the rssreader.dll and adds its .NET classes to Omnis using the $addclass() method.

Do FileOps.$splitpathname(sys(10),lDrive,lPath,,)
Calculate lPath as con(lDrive,lPath,'rssreader.dll')
Do DNet.$addclass(lPath)

Note the DNet object is part of the $root.$extobjects group. The next part of the method loads the System.Xml library and adds this to Omnis. You can use the $basefolder() method to return the folder containing your .NET Framework:

Do DNet.$basefolder Returns lPath
# lPath is something like C:\WINNT\Microsoft.NET\Framework\<version>
Calculate lPath as con(lPath,'\System.Xml.dll')
Do DNet.$addclass(lPathReturns #F

The next part sets up and builds a list containing the list of RSS feeds and loads the first one in the list:

Do iItemList.$define(iItemTitle,iItemDes,iItemLink,iItemPubDate)
Do method $buildurllist
Do iUrlList.$first()
Do iUrlList.$loadcols()

The next part of the window $construct() method creates an instance of the getRssFeed object and constructs the object in .NET using the $createobject() method. Finally, a class method is called to retrieve the feed.

Do $root.$extobjects.DNet.$objects.//NET\rssreader\rssreader\getRssFeed//.$newref() Returns iFeedObject
Do iFeedObject.$createobject()
Do method $getfeed

You can use the Interface Manager to examine the properties and methods of a .NET object. For example, this is the iFeedObject object created in the RSS feed window.

image10

The $buildurllist and $getfeed methods are contained in the window class and are called from the window $construct() method. The $buildurllist method builds a list containing a single column of RSS feed URLs which in this case are loaded from a static list of URLs, but could have been constructed from a database.

Do iUrlList.$define(iFeedLink)
Do iUrlList.$add('http://feeds.foxnews.com/foxnews/latest?format=xml')
# and so on...

The $getfeed method retrieves the XML source file for the current RSS feed and extracts the relevant information to display in the window.

# $getfeed method
Do iItemList.$clear()
Calculate iFeedObject.$rssurl as iFeedLink
Working message Waiting/-1073735814,-1073735810;50;0;60 {Retreiving RSS Feed} ## message while object is retrieved
Do iFeedObject.$getdocument() ## the XML source is retrieved
# Get the channel XmlNode and extract the channel information
Calculate lXmlNodeObject as iFeedObject.$channelnode
Do method $getchannelinfo (lXmlNodeObject)
For lItemNumber from 1 to iFeedObject.$numberofitemtags step 1
 Do iFeedObject.$getitemtags(lItemNumberReturns lXmlNodeObject
 Do method $getiteminfo (lXmlNodeObject)
End For

The $getchannelinfo method retrieves the title, language, and description for the RSS document while the $getitemtags method returns the information about each news story listed in the RSS feed including the URL, title, description, and publication date.

# Local var: lSubNode (Object) subtype NET\Xml\System\Xml\XmlNode
Do pRssItemNode.$selectsinglenode("link"Returns lSubNode
Calculate iItemLink as lSubNode.$innertext
Do pRssItemNode.$selectsinglenode("title"Returns lSubNode
Calculate iItemTitle as lSubNode.$innertext
Do pRssItemNode.$selectsinglenode("description"Returns lSubNode
Calculate iItemDes as lSubNode.$innertext
# ignore all html tags
If pos('<',iItemDes)<>0
 Calculate iItemDes as left(iItemDes,pos('<',iItemDes)-1)
End If
Do pRssItemNode.$selectsinglenode("pubDate"Returns lSubNode
Calculate iItemPubDate as lSubNode.$innertext
Do iItemList.$add(iItemTitle,iItemDes,iItemLink,iItemPubDate)
Calculate iItemPubDate as ''
Calculate iItemDes as ''

When you double-click on a news story in the RSS feed window, Omnis uses the URL stored in iItemLink (loaded from the iItemList) to launch a browser window and display the news story.

Method Method Overloading and Pattern Matching

Although Omnis Studio does not normally support the overloading of method names, the .NET Objects component is an exception as method overloading is usually unavoidable when dealing with even the most basic of .NET classes. The following sections discuss how Omnis deals with overloaded methods and how it is possible to manually call an overloaded method directly from Omnis.

Pattern Matching

Omnis uses pattern matching in order to determine the overloaded method that you’re trying to call. In simple terms, Omnis examines the parameters that you pass to a method and attempts to call the method whose parameters most closely match the parameters that you are passing. For example, consider the following .NET methods:

myfunc(int p1)
myfunc(float p1)

Calling myfunc from Omnis using an Omnis Number type set to Long Integer will call myfunc(int p1). Calling myfunc from Omnis using an Omnis Number type set to Floating dp will call myfunc(float p2).

Overloaded Data Types

An extra level of complexity is added to Pattern Matching with the support of Overloaded Data Types. An Overloaded Data Type is an Omnis data type that has more than one matching data type in .NET. Overloaded Data Types are split into three groups, described in the following sections.

Number Long Integer types

The Omnis Number Long Integer type can be translated to the following .NET types:

If a Number Long Integer type is passed to an overloaded method, the following occurs:

(int,boolean,long)
(long,boolean,int)
(long,boolean,long)

(byte,boolean,int)
(int,boolean,byte)
(byte,boolean,byte)

Note that any method that matches the “int” Parameter Search pattern will always be called if it is available. For example, consider the following .NET methods:

myfunc(int p1)
myfunc(long p1)
myfunc(byte p1)
myfunc(boolean p1)

calling myfunc using a Long Integer type will always call myfunc(int p1) in .NET. If this method is removed:

myfunc(long p1)
myfunc(byte p1)
myfunc(boolean p1)

calling myfunc using a Long Integer type will always call myfunc(long p1), and so on.

Number Floating dp types

The Omnis Number Floating dp type can be translated to the following .NET types:

If a Number Floating dp Omnis type is passed to an overloaded method, the following occurs:

(double,boolean,float)
(float,boolean,double)
(float,boolean,float)

(double,boolean,decimal)
(decimal,boolean,double)
(decimal,boolean,decimal)

Note that any method that matches the “double” Parameter Search pattern will always be called if it is available. For example, consider the following .NET methods:

myfunc(double p1)
myfunc(float p1)
myfunc(decimal p1)
myfunc(boolean p1)

calling myfunc using a Number Floating dp type will always call myfunc(double p1) in .NET. If this method is removed:

myfunc(float p1)
myfunc(decimal p1)
myfunc(boolean p1)

calling myfunc using a Floating dp type will always call myfunc(float p1), and so on.

.NET Object types

The Omnis .NET Object type can be translated to the following .NET Types:

When matching objects, Omnis will always try to find a method which takes an object parameter that matches the type of the object that you are passing. So if you pass a .NET.System.String object to an overloaded method, Omnis will look for a match using .NET.System.String as a search pattern. If Omnis fails to find a matching method, then Omnis will call a method which takes the generic type .NET.System.Object as a parameter, if such a method is available. Therefore, if Omnis searches for a method using the Parameter Search Pattern (String,boolean,String) and a matching method is not found, Omnis will look for (Object,boolean,String) followed by (String,boolean,Object) followed by (Object,boolean,Object).

Note that any .NET method that has a parameter list which matches the Objects that you are using as parameters will always be called if it is available. For example, consider the following .NET methods:

myfunc(String p1)
myfunc(Object p1)
myfunc(boolean p1)

calling myfunc using an Omnis object whose subtype is set to “.NETObjs\System\.NET\lang\String” will always call myfunc(String p1) in .NET. If this function is removed:

myfunc(Object p1)
myfunc(boolean p1)

calling myfunc using an Omnis object whose subtype is set to “.NETObjs\System\.NET\lang\String” will always call myfunc(Object p1).

Char and Byte Pattern Matching

The following table shows how Omnis converts Character and Binary data types to .NET data types when dealing with overloaded methods.

Omnis .NET
character types (length > 1) char[]
binary types (length > 1) byte[]
character types (length <= 1) char
binary types (length <= 1) byte

As a result of these conversions, you should be aware that it is not possible for Omnis to call an overloaded .NET function that takes char[] as a parameter using a single character. This is demonstrated in the following example. Consider the following:

myfunc(char p1[])
myfunc(char p1)

Following the rules for data conversion, calling myfunc with a single character will call myfunc(char p1) while calling myfunc with a string of characters will call myfunc(char p1[]). Thus, in this situation it is not possible to call myfunc(char p1[]) with a single character as myfunc(char p1) will always be called if the length of the data that you are passing is 1. However, it is possible to force Omnis to call myfunc(p1[]) with a single character if you call the overloaded method directly. The procedure for doing this is discussed in the next section.

Note: If the length of an Omnis Character type is 0, it will be converted into a .NET char type whose value is 0. If the length of an Omnis Binary type is 0, it will be converted into a .NET byte type whose value is 0.

Calling Overloaded Methods Directly

In some rare cases, it may be necessary to call overloaded methods directly. Consider the following example: you may be trying to call overloaded functions in the .NET.System.String Class. The functions are defined in .NET as follows:

compareto(Character c)
compareto(Object o)

If you want to call a particular method directly, you can do so from the Omnis Interface Manager, by selecting the desired overloaded method that you wish to call and clicking on the description tab. This will display the “real name” of the overloaded method.

The following screenshot shows the Omnis Interface Manager for the “.NET.System.String” class. If you were to call the $compareto() method using an Omnis “object” type, you must use the “real name” of this method which, in this case, is $valueof{o}.

image11

Note: Each parameter is separated by an underscore (_).

The naming convention for these parameters are as follows:

.NET Type Abbreviated to (Omnis type)
Char “c”
boolean “b”
Decimal “d”
Float “f4”
Double “f8”
Unsigned Byte “u1”
Signed Byte “i1”
Unsigned Short “u2”
Signed Short “i2”
Unsigned Int “u4”
Signed Int “i4”
Unsigned Long “u8”
Signed Long “i8”
Object “o”
Object of known type
Enum
Void “v”

An additional ‘p’ character means pointer (or *) and an ‘a’ character means an array.

Nested Object Arrays

The .NET Objects component supports Nested Object Arrays as parameters to .NET methods, and it can also interpret Nested Object Arrays returned from .NET. A Nested Object Array is an array of type .NET.System.Object that is capable of storing any .NET Object or Array of .NET Objects.

To use a Nested Object Array, you must create an Omnis List variable and define it using a Binary variable. You can then add .NET Objects and lists of .NET Objects to the list. Once your list is complete, you can pass it to any .NET method that accepts .NET.System.Object array as a parameter.

Nested Object Arrays can also be returned by .NET methods. A Nested Object Array is returned to Omnis as a Binary list. This list may contain both Object References and embedded Lists.

Overloaded Types

The following sections provide detailed descriptions of the Overloaded Types used by the .NET Objects component.

Omnis Character types

The Omnis Character type can be converted into the following .NET types:

Char

char[]

This allows you to call any .NET object that takes either a char or char[] as a parameter with an Omnis Character variable. You may also place .NET return values that are of type char or char[] into an Omnis Character variable.

In the case of “char[]” parameters, the Omnis Character variable is automatically converted into a .NET char array (or vice versa if you are dealing with return values). This allows objects such as the .NET String to be created easily from Omnis. For example:

Calculate mychar as "hello this is a test"
Do mystring.$createobject(mychar)

The above will invoke the .NET String Constructor String(char[] value)

Note: If you attempt to call a .NET function that takes a single char as a parameter and the Omnis variable that you are passing contains more than one character, .NET will only receive the first character of the string.

Omnis Binary types

The Omnis Binary type can be converted into the following .NET types:

Byte

byte[]

This allows you to call any .NET object that takes either a byte or byte[] as a parameter with an Omnis Binary variable. You may also place .NET return values that are of type byte or byte[] into an Omnis Binary variable.

In the case of “byte[]” parameters, the Omnis Binary Type is automatically converted into a .NET byte array (or vice versa if you are dealing with return values). This allows objects such as the .NET String to be created easily from Omnis. For example:

Do mystring.$createobject(mybinval)
# where mybinval is a binary Omnis Variable

The above will invoke the .NET String Constructor String(byte[] bytes)

Note: If you attempt to call a .NET function that takes a single byte as a parameter and the Omnis variable that you are passing contains more than one byte, .NET will only receive the first byte of the data that you are passing.

Omnis Number Long Integer types

The Omnis Number Long Integer type can be converted into the following .NET types:

Int

long

byte

This allows you to pass Omnis Number Long integer variables to .NET functions which accept these types.

Note: When dealing with return values, .NET int and long types can be converted into the Omnis Number Long integer type. However, all byte return values are always converted to the Omnis Binary type.

Omnis Number Floating dp types

The Omnis Number Floating type can be converted into the following .NET types:

Float

double

This allows you to pass Omnis Number floating dp variables to .NET functions which accept these types.