COM DLL Support in TDL
A dynamic link library (DLL) is an executable file that acts as a shared library of functions. Dynamic linking provides a way for a process to call a function that is not part of its executable code. The executable code for the function is located in a DLL, which contains one or more functions that are compiled, linked, and stored separately from the processes that use them. Multiple applications can simultaneously access the contents of a single copy of a DLL in memory.
DLL support has been provided in TDL for quite a while. The focus was primarily on extending Tally for bringing in capabilities which could not be achieved within Tally. ‘CallDLLFunction’ allowed calling native/unmanaged DLLs which were written and compiled in C++.
In further releases, this moved a step further where the support was extended to use Plug-In and Activex Plug-In , where the XML output from the DLL could be used as a data source in the collection artefact, and thereby, consumed in TDL. This paved the way for new possibilities on extending Tally as per customer needs, which required interactions with external hardware, etc. However, this required changes in the DLL as per the processing capabilities of the collection. The XML output from the collection had to be necessarily from a function within DLL which had to be named mandatorily as TDLCollection within the DLLClass.
The Component Object Model (COM) is a component software architecture that allows applications and systems to be built from components supplied by different software vendors. COM is the underlying architecture that forms the foundation for higher-level software services. These DLLs provide the standard benefits of shared libraries. Component Object Model (COM) was introduced by Microsoft to enable inter-process communication and dynamic object creation across a varied range of programming languages. In other words, objects can be implemented in the environment t s seamlessly different from the one in which they are created. This technology specifies manipulation of data associated with objects through an Interface. A COM interface refers to a predefined group of related functions that a COM class implements. The object implements the interface by using the code that implements each method of the interface and provides C OM binary-compliant pointers to those functions, to the COM library. COM then makes those functions available to the requesting clients.
COM DLL Support will pave t h e way for providing features like ‘Tally For Blind’ using the generic speech API provided by Microsoft. This Release comes with enhanced capabilities in the language to support COM D L L processing. A new definition type called COM Interface has been introduced for the same.
This capability has been introduced in Tally.ERP 9 Release 4.6
COM Servers and COM Clients
A COM Server is any class/method that provides services to clients. These services are in the form of interface implementations which can be called by any client that is able to get a pointer to one of the interfaces on the server object. A COM Client makes use of a COM Server, and uses its services by calling the methods of its interfaces.
COM Server DLLs are DLLs which have objects exposed to COM and can be used by COM Clients. Let’s take the following DLL Code as an example:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MathLib
{
public class MathClass
{
public double Add(double pDouble)
{
return pDouble + 9;
}
public int Divide(int Dividend, int Divisor, out int Remainder)
{
int Quotient ;
Quotient = Dividend / Diviso r ;
Remainder = Dividend – (Divisor * Quotient); return Quotient;
}
public void datefunc(ref DateTime date)
{
date = date.AddDays(40);
}
}
}
In C# DLL, three functions are called. They are:
- Add – It takes an input parameter, and returns it, after adding 9 to it.
- Divide – It accepts a Dividend and a Divisor as inputs, and returns the Quotient, along with the Remainder.
- datefunc – It accepts a parameter ‘date’ as input, and updates it by adding 40 days to it.
Registering the DLL
For . NET COM Servers, we need to register with a parameter/CodeBase.
Example
regasm/Code Base <DLL Name with absolute path>
Registering COM DLLs
To register DLLs on 32-bit operating system
- Go to the folder where 32-bit windows Microsoft.net framework. Generally, Microsoft.net framework is available at C:\Windows\Microsoft.NET\Framework.
- Choose the latest version of .NET\Framework.
- Copy the folder path where the regasm.exe is available. For example, C:\Windows\Microsoft.NET\Frameworkv4.0.30319 .
- Open Command Prompt in administrator mode.
- Replace the path using the command: cd /d C:\Windows\Microsoft.NET\Framework\v4.0.30319 .
- Place the DLL in TallyPrime folder and copy the entire path.
- Register the DLL using regasm/codebase “G:\Tally\Tally 5.3.4\TFI.dll” .
To register the DLL on 64-bit operating system
- Go to folder where 64-bit windows Microsoft.net framework. Generally, the Microsoft.net framework is available at C:\Windows\Microsoft.NET\Framework64 .
- Choose the latest version of .NET Framework.
- Copy the folder path where the regasm.exe is available. For example, C:\Windows\Microsoft.NET\Framework64\v4.0.30319 .
- Open Command Prompt in administrator mode.
- Replace the path using the command: cd /d C:\Windows\Microsoft.NET\Framework64\v4.0.30319 .
- Place the DLL in Tally.ERP 9 folder and copy the entire path.
- Register the DLL using the command. For example, regasm/codebase “G:\Tally\Tally 5.3.4\TFI.dll” .
For further details on steps to register DLLs, please refer to the section How to Register DLLs .
If the DLL is written using VB.NET or C#.NET; before building the DLL, please ensure that the COM Visible Property is set. After registering the DLL, ensure that the registry entries are available as under:
ProgID: The value for which should be <ProjectName>.<ClassName>
Inprocserver32 OR InprocHandler32 OR LocalService – The default value for these keys in registry should be the path to the DLL/EXE which we have registered.
To find the Registry Entry, one can open regedit, and locate the project name of the DLL that has been registered and ensure the above.
Implementation in TallyPrime or Tally.ERP 9 Using TDL
A new definition ‘COM Interface’ has been introduced to call a function available in external DLL/ EXE (COM Server). This will help the TDL Developer to use external libraries and devices. Now TallyPrime or Tally.ERP 9 can now act as a COM Client.
Definition – COM Interface
The definition ‘COM Interface’ has been introduced to accept the external DLL/EXE details like Project name, Class name, Function name and other required parameters.
Syntax
[COM Interface : <COM Interface Name>]
Where,
<COM Interface Name> is the name of the COM Interface definition.
Attributes Supported by Definition COM Interface
The following attributes are supported in this definition:
Attribute – PROJECT
This attribute is used to specify the name of the project.
Syntax
Project : <Project Name>
Where,
<Project Name> is the name of the Project/Name space of the COM Server.
Attribute – CLASS
This attribute is used to specify the Class name under the project specified.
Syntax
Class : <Class name>
Where,
<Class Name> is the name of the Class of the COM server to be used.
Attribute – INTERFACE
This attribute is used to specify the interface name under the class that needs to be executed. It corresponds to the name of the function within the DLL Class to be executed.
Syntax
Interface : <Interface Name>
Where,
<Interface Name> is the name of the actual Interface name of the DLL which is to be called.
Attribute – PARAMETER
This attribute denotes the list of parameters along with their data types required by the COM Interface. The TDL Data types supported are:
- Number
- Long
- String
- Logical
- Date
Syntax
Parameter : <Parameter Name> : <Data type> [: <Parameter Type>]
Where,
<Parameter Name> is the name of the Parameter.
<Data Type> is the data type of the parameter being passed.
<Parameter Type> is the nature of the parameter, viz. In (Input), Out (Output) or InOut (Both Input and Output)
Example
Parameter of type String for accepting output will be written as:
Parameter : Parm1 : String : Out
In the absence of the specification of the nature of Parameter, the parameter is defaulted as in parameter.
All the parameters must sequentially correspond to the ones accepted by the COM Interface.
Attribute – Returns
This attribute denotes the return data type of the COM Interface.
Syntax
Returns : <Return Data Type>
Where,
<Return Data Type> is the data type of the value returned by the COM Interface. Let us define the COM Interfaces required for the previous DLL code:
[COM Interface : TSPL Smp Addition]
Project : MathLib
Class : MathClass
Interface : Add
Parameters: p1 : Number : In
Returns : Number
[COM Interface : TSPL Smp Division]
Project : MathLib
Class : MathClass
Interface : Divide
Parameters : p1 : Long : In
Parameters : p2 : Long : In
Parameters : p3 : Long : Out
Returns : Long
[COM Interface : TSPL Smp AddDate]
Project : MathLib
Class : MathClass
Interface : DateFunc
Parameters : p1 : Date : InOut
In this code, 3 COM Interfaces are defined, each for executing 3 different functions inside DLL:
- MathLib is the DLL Project Name.
- MathClass is the DLL Class under the Project MathLib.
- Add, Divide and DateFunc are the Functions under the Class MathClass, which are specified in the Attribute Interface.
Action – Exec COM Interface
A new action Exec COM Interface has been introduced to invoke the defined COM Interface.
Syntax
Exec COM Interface: <COM Interface name> [: <Parameter 1> [: <Parameter 2>…… [: <Parameter N>]…]]
Where,
<COM Interface Name> is the name of the COM Interface Definition.
[: <Parameter 1> [: <Parameter 2> …… [: <Parameter N> ]…]] are the subsequent parameters, which are passed considering the following aspects:- If the parameter corresponds to IN parameter, it can take any expression or constant.
- If the parameter corresponds to an OUT or an InOut Parameter, then only the variable name must be specified, without prefixing a ##. In other words, expressions are not supported. The variable, in case of:
- InOut Parameter will send the variable value to the Interface as input, and in r e turn, will bring back the value altered by the Interface.
- OUT Parameter , will only bring back the updated value from the DLL .
In the previous TDL Code, three COM Interfaces are defined. A function is then called, inside which the action Exec COM Interface is used to invoke the COM interface definitions as follows:
[Function : TSPL Smp Execute COM Interfaces]
Variable : p1 : Number : 90
Variable : p2 : Number : 102
Variable : p3 : Number : 5
Variable : p4 : Number
Variable : pDate : Date
00 : Exec COM Interface : TSPL Smp Addition : ##p1
10 : Log : $$LastResult
20 : Exec COM Interface : TSPL Smp Division : ##p2 : ##p3 : p4
25 : Log : $$LastResult
30 : Log : ##p4
40 : Set : pDate : $$Date:”20-04-2013″
50 : Exec COM Interface : TSPL Smp AddDate :pDate
60 : Log : ##pDate
If this action is invoked from within a TDL function, then the Objects created are retained until all the Actions within the function are executed. This behaviour was designed so that multiple functions in a COM Class can be used on the same COM Object (state of COM Object is maintained). For instance, there are some functions of a COM server which depend on each other, and are required to be called in sequence, then the same object needs to be present and functions should be called on that same object to give correctness.
As a Global action, this would create a COM Object once per COM Interface execution. In other words, if there are two functions of a COM Server and they depend on each other, then this action would work only if used within a procedural Code.
Function – $$COMExecute
This function is similar to the Action Exec COM Interface , except that Interfaces with only In Parameters can be executed with the Function $$COMExecute. In other words, this Function can only execute a COM Interface , if it has no Out Parameters.
Syntax
$$COMExecute : <COM Interface name>: [<Parameter 1>[:<Parameter 2> [….[: <Parameter n>]….]]]
Where,
<COM Interface Name> is the name of the COM Interface definition.
[<Parameter 1>[:<Parameter 2>[….[:<Parameter n>]….]]] are the IN parameters, which correspond to the parameters specified in the COM Interface definition.As mentioned earlier, the first function of DLL only takes In Parameters. Hence, the function COMExecute can be used only for the first COM Interface definition in the example shown above.
Example
$$COMExecute:TSPLSmpAddition:##p1
Function – $$IsCOMInterfaceInvokable
This function checks if the ‘COM Interface’ description which was defined, could be used or not. If the COM class of the interface is not available in the COM server, it would return FALSE; while if the class and the function invoked in the COM class are present, then the interface is invokable, and hence TRUE would be returned.
Syntax
$$IsCOMInterfaceInvokable : <COM Interface Name>
Where,
<COM Interface Name> is the name of the COM Interface Definition.
Scope and Limitations
- Only a COM Server which implements its classes using IDispatch interface (Automation interface of COM), can be used with this.
- For other Native DLLs (DLLs that contain raw processor directly-executable code, e.g., Win32 DLL) or ones which do not comply with the above, another wrapper DLL can be made which makes use of it and exposes the functionality to TDL.
- The data types supported are Long, Number, String, Logical and Date, which are mapped to the following data types in TDL:
TDL Type |
Parameter data type in TDL |
Signed Int |
Long |
Double |
Number |
Double |
String |
Boolean |
Logical |
Date |
Date |
- Out parameters are supported in this capability. But, functions which take other data types than specified in the table are currently not supported in TDL, and hence, cannot be used.
COM Data Types Support
In Release 4.6, a new Definition Type COM Interface, a new Action Exec COM Interface, and new Functions $$COMExecute and $$IsCOMInterfaceInvokable had been introduced to extend Support for COM Servers. However, this support was limited to only a few COM Data Types.
From Release 4.61 onwards, the following COM Data Types will also be supported:
COM Data Type |
TDL Data Type |
Other Permissible TDL Data Types |
Range of Values/Other Details |
String |
String |
Number, Date, Logical, Amount |
|
Float |
Number |
String, Amount |
3.4 * 10^-38 to 3.4 * 10^38 |
Double/Number |
Number |
String, Amount |
1.7 * 10^-308 to 1.7 * 10^308 |
Currency/Amount |
Amount |
String, Number |
This would have a precision of 4 decimal places, rather than 5, as in Tally.ERP 9. If Tally sends the number in 5 decimal places, DLL will round it off to 4 decimal places. |
Char |
String(1st character of String is used) |
Number, Date, Logical, Amount (Only the First letter) For e.g., if the number is 987, then the result char would be 9 and similarly, for the other data types. For Date, it depends on the Date Format. |
Single Character |
Byte/Unsigned char |
Number |
String, Amount |
0 to 255 |
Short/Wchar |
Number |
String, Amount |
-32,768 to 32,767 |
Unsigned short |
Number |
String, Amount |
0 to 65,535 |
Long |
Number |
String, Amount |
-2,147,483,648 to 2,147,483,647 |
Long Long |
Number |
String, Amount |
-9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 |
Unsigned Long |
Number |
String, Amount |
0 to 4,294,967,295 |
Unsigned Long Long |
Number |
String, Amount |
0 to 18,446,744,073,709,551,615 |
Integer |
Number |
String, Amount |
-2,147,483,648 to 2,147,483,647 |
Unsigned Integer |
Number |
String, Amount |
0 to 4,294,967,295 |
Bool/Boolean/ Logical |
Logical |
String (Yes/No, 0/1, True/False) |
True/False |
Date |
Date |
String |
|
Variant |
String, Number, Date, Logical, Amount |
|
This can be an Out or InOut parameter. The value for the data type can be any one of the following data types, viz String, Amount, Number, Date OR Logical. |
Scode |
Number |
String |
0 to 4,294,967,295 This is a kind of an error code data type, used by Windows API. |
The parameters can also be of the Other Permissible TDL data types, as mentioned in the table, in place of the data types mentioned in the column titled ‘TDL Data Type’. Irrespective of whether the parameter is an In, Out OR InOut parameter, Tally implicitly converts these data types to the respective COM Data Types.
In Release 4.6, while declaring the Parameters for COM Interface, only a limited number of data types could be accepted as a data type for the parameter. Let’s understand this with the help of the following example:
DLL Code |
TDL Code – COM Interface Definition |
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace MathLib { public class MathClass { public double Add(double pDouble) { return pDouble + 9; } } } |
[COM Interface : TSPL Smp Add] Project : MathLib Class : MathClass Interface : Add Parameters : p1 : Number : In Returns : Number |
In the codes shown in the table, the Interface Add of Class MathClass had the Parameter Data type as Double in DLL, while the same had to be mapped to Number as the Parameter Data type in TDL.
From Release 4.61 onwards, the COM Data Types listed in ‘Other Permissible TDL Data Types’ column in the table are also supported. Thus, in this particular example, the data type of the Parameter can also be specified as Double in place of Number, and hence, the same can be rewritten as:
Parameters : p1 : Double : In
However, while invoking the COM Server, the data type must be a TDL Data Type, viz. Number, String, Amount, Date OR Logical.
Example
[Function : TSPL Smp Addition]
Parameter : InputNo : Number
00 : Exec COM Interface : TSPL Smp Add : ##InputNo
10 : Log : $$LastResult
It is not necessary to have the above TDL Data Type as Number. It could also be a String or an Amount. However, the value within the String should be a Number.