COM and Uniface Parameter Data Types

Converting Uniface parameter data types to and from the COM environment has both a static and dynamic nature. When you export a COM Interface DLL, the data types of the signature definitions must be matched to the appropriate COM types, taking into account the user’s implementation selections. At runtime, both Uniface and COM allow the user to pass variants for parameters, so the connector can dynamically convert data types, within reason.

Export COM Interface DLL

The COM data types that you can use must comply with the IDispatch interface, which is based upon the data types that can be transported through a COM VARIANT structure. The COM type names listed in the table are the VARIANT union tag values:

Uniface-COM Data Type Mappings
Uniface 4GL data type Default exported COM data type Visual Basic Type
String VT_BSTR (a Unicode string) String
Handle VT_DISPATCH Object
Boolean VT_BOOL Bool
Numeric VT_I4 (a 4-byte integer) Long
Float VT_R8 (an 8-byte float) Double
Date VT_DATE, time part is 00:00:00. Date
Time VT_DATE, date part is today. Date
Datetime VT_DATE Date
Linear Date VT_DATE Date
Linear Time VT_DATE Date
Linear DateTime VT_DATE Date
Raw VT_ARRAY | VT_UI1 (an array of bytes) Dim VAR() As Byte
Image A standard COM IPicture object IPicture
Entity See Call-Out ADOR.Recordset
Occurrence Treated as a one-record UTYPE_ENTITY ADOR.Recordset

These are only the default conversions applied at COM Interface DLL export time. It is possible for the user to change the service after the COM Interface DLL is exported and it is also possible for a COM client to call a service without adhering to the definition in the type library.

Additional COM data types can be used if, for example, a Uniface type should be mapped to a different COM data type. These non-default values are available in the drop-down list in the Define Parameter dialog in the Signature Editor.

Linear Date/Time Handling

The default data type in the Signature Editor for Linear values is COM’s VT_DATE. If the user chooses to convert a Uniface LinearDate or LinearDateTime to a numeric-based type, for example, VT_R8 or VT_I4. The epoch used is the Uniface epoch (the day before 01-Jan-0000), not the COM epoch (30-Dec-1899).

The Uniface epoch is based upon a value of 1.0 on 01-Jan-0000. The COM epoch is based upon a value of 1.0 on 31-Dec-1899. Uniface expresses 31-Dec-1899 as 693961.0.

If the developer passes a Uniface LinearDate to a Visual Basic Date, and Visual Basic subsequently converts it to a Double. A different result is returned than if the LinearDate is passed directly to a Double.

If the user chooses to convert a Uniface LinearTime to a numeric-based type, such as VT_R8 or VT_I4, the result will be a floating-point value that contains the fractional part of a day. For example, 06:00 hours is expressed as 0.25 and 12-noon is expressed as 0.5.

Call-Out

A connector converts whatever data is passed from the client Uniface service to a data type that is expected by the called COM object. This happens independently of the 4GL signature or the imported type library.

For call-out, the activate statement uses the Signature Editor definitions to initially validate the parameters, then the COM connector completes the activate request by using the COM method interface published by the COM object.

It is not normally necessary for the Signature Editor definitions to exactly match the COM interface, as the COM connector will convert the Uniface data types as required. However, the parameter directions (IN, OUT, INOUT) must be set correctly in the Signature Editor. In addition, Uniface parameters that are actually Uniface instances (and therefore must be treated as COM objects), must be properly indicated in the Signature Editor with the Handle data type and the classification name that this parameter maps to.

The UTYPE_IMAGE type can only be converted to:

  • A COM IPicture object
  • A VT_ARRAY of VT_UI1 (an array of bytes)

When exporting a service operation into a type library, a call-out entity parameter (UTYPE_ENTITY) is always exposed as a standard COM ActiveX Data Objects (ADO) Recordset object. A Recordset is similar to a Uniface entity; it has multiple records of fields, a current record, and you can insert and remove occurrences. ADO is a high-level standard for data access in the Microsoft environment.

The COM client can choose not to adhere to the type library definitions and call the Uniface operation with another COM data type.

Call-in

It is customary for COM clients to adhere to the interface definition that is in the type library, but it is not required. So-called ‘scripting’ environments do not require any type information on the client side. For this reason, the call-in data mapping within the connector needs to be complete.

The UTYPE_IMAGE data type requires an image, consequently, the COM connector expects a VT_DISPATCH or VT_UNKNOWN that points to an IPicture to be passed to the Uniface parameter. An array of bytes is also permitted.

Entity parameters are handled in a manner similar to that of the call-out situation.

COM arrays can be mapped to either a Uniface entity or a Uniface string list. The type of the Uniface formal parameter determines the exact conversion.

COM operation implementation

The following examples show the implementation for two operations, both of which return the number one. The first operation is implemented in Uniface, the second operation is implemented in Microsoft Visual Basic.

Call a Uniface service that returns a value 1

The assignment file contains the following setting:

KURB040UF = $COM:KURB040UF CLASS=KURB.KURB040UF

The signature for the service KURB040UF contains the following definitions:

implementation: COM;
operation: COM_1;
parameter: VALUE (numeric, out)
implementation: Uniface Service (default)
Form KURB040, Button Uniface, detail trigger:
variables
Handle kurb040uf
;RT testcase 10
endvariables
newinstance "kurb040uf", kurb040uf
;RT testcase 11
kurb040uf->com_1(u_return)

Service KURB040UF:

operation COM_1
params
numeric value : out
endparams
putmess "%%$componentname%%% operation COM_1 called"
value = 1
end ; operation COM_1

Call a Visual Basic object that returns a value 1

The assignment file contains the following setting:

KURB040VB = $COM:KURB040VB CLASS=KURBTESTSVB.KURB040VB

The signature for the service KURB040VB contains the following definitions:

Implementation: COM;
operation: COM_1;
parameter: VALUE (numeric, out)

Form KURB040, Button Visual Basic, detail trigger:

trigger detail
newinstance "kurb040vb", kurb040vb
variables
  Handle kurb040uf
endvariables
kurb040vb->com_1(u_return)
end

Visual Basic code:

Public Function com_1(value As Long) As Long
Open "kurb040vb.log" For Append As #1
Write #1, Now
Write #1, "Case 2: kurbtestsvb.kurb040vb.com_1 called"
value = 1
com_1 = 0
Close #1
End Function

Excel

The following example shows how to call a specific cell in an Excel spreadsheet, and retrieve its value. The assignment file contains the following setting:

KURB040ME = $COM:KURB040ME CLASS=KURB.KURB040ME

The Signature Editor contains the following definitions:

Component: KURB040ME;
implementation: COM;
operation: VISIBLE;
parameter X (boolean, IN)
literalname: VISIBLE.SET
operation: WORKBOOKS;
parameter: X, connected to KURB040MEWB
operation: CELLS;
parameter: ROW (numeric, IN)
parameter: COL (string, IN)
operation: QUIT;
parameter: none
signature: KURB040MEWB;
implementation: COM;
operation: OPEN
parameter: FILENAME (string, IN)
operation: CLOSE
parameter: none

Call a specific Excel spreadsheet cell

This example illustrates how to call a specific cell in an Excel spreadsheet, and retrieve its value.

The assignment file contains the following setting:

KURB040ME = $COM:KURB040ME CLASS=KURB.KURB040ME

The Signature Editor contains the following definitions:

Component: KURB040ME;
implementation: COM;
operation: VISIBLE;
parameter X (boolean, IN)
literalname: VISIBLE.SET
operation: WORKBOOKS;
parameter: X, connected to KURB040MEWB
operation: CELLS;
parameter: ROW (numeric, IN)
parameter: COL (string, IN)
operation: QUIT;
parameter: none
Signature: KURB040MEWB;
implementation: COM;
operation: OPEN
parameter: FILENAME (string, IN)
operation: CLOSE
parameter: none

The form KURB040 is painted with a Command Button called ’Excel’. The detail trigger of this button contains the following ProcScript:

; activate application
newinstance "kurb040me",$1

; set property visible=true
$1->visible(1)

; activate method workbooks, returning an object reference
$1->workbooks($2)

; open a spreadsheet
$2->open("kurb_com.xls")

; retrieve the value in cell A1 into $status
$1->cells(1,"A")

; activate close method, closing the workbook
$2->close()

; activate quit method, removing the application
$1->quit()

Spreadsheet kurb_com.xls, Sheet KURBO40, Cell A1 contains the value "1".

Call-in from Visual Basic

The following example illustrates how to call a Uniface operation (com_callin) in a service (kurb041s) from a Visual Basic subroutine.

Private Sub Command1_Click()
Dim value as Long
Dim result as Long
Dim svc As kurb041s
Dim rc As Long

Set svc = New [Uniface components kurb_call_in].kurb041s
result = svc.com_callin(value)

End Sub