Introduction
In the previous article, I described basic steps to create a COM component in MATLAB that can be used in any language or IDEs supporting COM features. The required steps for creating a full feature COM component are:
- Adding Class Methods and Properties to COM Builder Objects
- Adding Events to COM Builder Objects
- Creating an Instance of a Class
- Calling the Methods of a Class Instance
- Processing
varargin
and varargout
Arguments
- Handling Errors During a Method Call
The first step (Adding Class Methods and Properties to COM Builder Objects) was described in the previous article and the others will be described here.
Adding Events to COM Builder Objects
MATLAB COM Builder supports events, or callbacks, through a simple MATLAB language pragma. You simply provide a MATLAB function stub that serves as the prototype for the event, and then provide an implementation of the function in your client code (Visual Basic, Visual C++, etc.). The net effect is that when any other MATLAB function calls the event function, the call is dispatched to the �event handler� in the client code.
You can turn a MATLAB function into an event function by placing a %#event
pragma into the code. MATLAB interprets this statement as a comment. When you include the same function as a method on a COM Builder object, the compiler generates an outgoing interface for the method, which identifies the method as an event. This outgoing interface is then implemented by the client code. Some examples of how you might use callbacks in your code are:
- To give a client application periodic feedback during a long running calculation. For example, if you have a task that requires n iterations, you might signal an event to increment a progress bar in the user interface on each iteration.
- To signal a warning during a calculation but continue execution of the task.
- To return intermediate results of a calculation to the user and continue execution of the task.
The following pseudo code illustrates the meaning of the above paragraph:
LongCalculation.m
function [x] = LongCalculation(n)
%initialize x
x = 0;
% Run n iterations, callback every inc time
for i=1:n
progress(i);
% Do some work on x...
x = x + 1;
end;
Progess.m
function progress(i)
%#event
%progress(i) is an event function
%the client must implement the event
i
When LongCalculation
runs, the event function progress(i)
will be called. In client side, developer can handle the event, for example, show a progress bar that graphically demonstrates the progress of the calculation. In Visual Basic, the event handler looks like this:
Sub CLASS_progress(ByVal i As Variant)
The CLASS is the name of a variable used for class instance. Notice that if you want to use your component in Visual Basic, you must declare an instance of your component with WithEvent
keyword.
In MATLAB, type comtool
to run COM Builder GUI, then create a new project and name it Example_Event
. Add LongCalculation.m and Progress.m to the project and build the COM component.
Now, run Visual Basic and create a new form consisting of a text box (txtNum
), a command button (cmdGo
) and a progress bar. See figure 1 for more details of the form. Add the following code to the form:
Private WithEvents MyVar As Example_Event.Example_Event
Private Sub Form_Load()
Set MyVar = New Example_Event.Example_Event
End Sub
Private Sub cmdGo_Click()
Dim d As Double
d = CDbl(txtNum.Text)
ProgressBar1.Max = d * 10
Call MyVar.longcalculation(0, 0, d * 10)
End Sub
Private Sub MyVar_Progress(ByVal i As Variant)
ProgressBar1.Value = i
End Sub
Creating an Instance of a Class
Creating an instance of a class (or a component) is easy. There are two types of syntaxes in Visual Basic:
- Using
CreateObject
function
- Using
New
operator
In the above section, you see how can use New
operator. Following code shows you how to use CreateObject
function.
Private Sub Form_Load()
Dim myVar As Object
Set myVar = CreateObject("Fourier.Fourier")
Dim x(1 To 601) As Double
Dim t(1 To 601) As Double
m = 1
For i = 0 To 0.6 Step 0.001
t(m) = i
x(m) = Sin(2 * pi * 50 * t(m)) + Sin(2 * pi * 120 * t(m))
m = m + 1
Next
myVar.x = x
Call myVar.addnoise(0, 0)
Call myVar.powerspectrum(0, 0)
End Sub
In this situation, there is no need to add Fourier type library to the project. The program automatically loads the component and uses it later. If you employ New
operator, you must add a reference to the project.
Calling the Methods of a Class Instance
After creating an instance of the component, it is possible to call methods of it. These methods are m-files of COM Builder project. In Fourier example (See previous article), we declared two methods: AddNoise
and PowerSpectrum
. Both of them are m-files (MATLAB functions) that we added to the project. MATLAB compiled them as methods of the component. For calling the methods, simply use Call
command from Visual Basic. Here is an example:
Dim myVar As New Fourier.Fourier
Call myVar.addnoise(0, 0)
Call myVar.powerspectrum(0, 0)
When a method has output arguments, the first argument is always nargout
, which is of type Long
. This input parameter passes the normal MATLAB nargout
parameter to the compiled function and specifies how many outputs are requested. Methods that do not have output arguments do not pass a nargout
argument. Following nargout
are the output parameters listed in the same order as they appear on the left side of the original MATLAB function. Next comes the input parameters listed in the same order as they appear on the right side of the original MATLAB function. All input and output arguments are typed as Variant
, the default Visual Basic data type.
The Variant
type can hold any of the basic VB types, arrays of any type, and object references. In general, you can supply any Visual Basic type as an argument to a class method, with the exception of Visual Basic UDTs. When you pass a simple variant type as an output parameter, the called method allocates the received data and frees the original contents of the Variant
. In this case, it is sufficient to dimension each output argument as a single Variant
. When an object type (like an Excel Range) is passed as an output parameter, the object reference is passed in both directions, and the object�s Value
property receives the data.
Following examples show you how to call a method with variant inputs or outputs:
y = myfunction(x1, x2)
Dim myComponent As Object
Dim result As Variant
myComponent = CreateObject("Component.Component.1_0")
Call myComponent.myfunction(1, result, x1, x2)
Processing varargin and varargout Arguments
When varargin
and/or varargout
are present in the original MATLAB function, these parameters are added to the argument list of the class method as the last input/output parameters. You can pass multiple arguments as a varargin
array by creating a Variant
array, assigning each element of the array to the respective input argument.
y = myfunction(varargin)
Dim myComponent As Object
Dim v(1 To 5) As Variant
Dim result As Variant
v(1) = x1
v(2) = x2
v(3) = x3
v(4) = x4
v(5) = x5
myComponent = CreateObject("Componen.Component.1_0")
Call myComponent.myfunction(1, result, v)
The MWUtil
class included in the MWComUtil
utility library provides the MWPack
helper function to create varargin
parameters. See following example for more details:
varargout = myfunction(x1, x2)
Dim myComponent As Object
Dim Util As Object
Dim v As Variant
Dim Xin1, Xin2 As Variant
Util = CreateObject("MWComUtil.MWUtil")
myComponent = CreateObject("Component.Component.1_0")
Call myComponent.myfunction(3, v, Xin1, Xin2)
Call Util.MWUnpack(v, 0, True, Xout1, Xout2, Xout3)
Handling Errors During a Method Call
If any error occurred when creating an instance of a component or passing an argument, the programmer can catch the error and some detailed information about the error and reason of it. The easiest way for handling error in Visual Basic is On Error
syntax. The Err
global variable has all of the needed information about the error. E.g.:
On Error Goto Handle_Error
Dim Util As Object
Util = CreateObject("MWComUtil.MWUtil")
...
Handle_Error:
MsgBox(Err.Description)
Enjoy!