If I wanted to act like an old fogey, I could reminisce and say I miss the good old days where we, at MathWorks, delivered
demos by using the function echo. But I can't honestly say I miss that aspect of writing demos. These days, we either create GUIs, often light-weight for
a demo, perhaps using guide or nested functions such as this example, OR, we write MATLAB code that we publish.
My question to you this week is: do you use the function echo currently? If so, can you please explain why/how (e.g., see no reason to update code, don't want to take the time to write
a GUI, etc.). Thanks. As always, let me know your thoughts here.
Grouping related functions into separate shared libraries is very common, as it promotes good software design and maintainability
via separation of concerns. A single application almost always calls functions from multiple shared libraries.
To show you how to build applications that use multiple MATLAB Compiler-generated shared libraries, I've written an example program that computes and displays the Mandelbrot set, a shape with a fractal boundary.
The application consists of three parts:
Two shared libraries, each generated by MATLAB Compiler.
A main program that interprets command line arguments and calls functions in the shared libraries.
Each of the MATLAB Compiler-generated shared libraries provides a specific kind of functionality: the libmandelbrot library performs mathematical calculations, while libimage displays images.
Building the Shared Libraries
Download the code for this example from MATLAB Central, unpack the ZIP files in a new folder, and then use the mcc command to create the shared libraries:
Note the use of -W cpplib, which creates C++ shared libraries. Functions exported from C++ shared libraries are easier to use than those exported from
C shared libraries.
mandelbrot returns the image data as an mwArray object, which the main program then passes to showimage. This demonstrates that an mwArray created in one shared library can be processed in another; an mwArray is independent of the shared library that created it.
showimage(fractal);
showimage creates an image from the image data and displays the image in a figure window.
Building and Running the Application
Compile the main program and link it with the two shared libraries using mbuild. The mbuild command varies by platform:
Then, create a Mandelbrot set 500 pixels wide with an iteration limit of 100 by running the fractal program:
fractal 500 100
Mandelbrot sets require a significant amout of computation. The example above takes about 45 seconds on a PC with a 2.5GHz
processor. A 2000-pixel wide set requires more than 15 minutes.
Have you ever written an application that uses multiple Compiler-generated libraries? Did it work as you expected? Let me
know here.
Recently at work I was on an email thread where people were discussing the function size and how to use it reliably in the context of arrays that might be two dimensional but could have higher dimensions as well.
The original solutions resorted to calling size multiple times.
There is a better way, however, and I pointed it out. The idea is to use ~ to capture all the remaining dimensions after the first two. Like so:
[rows, cols, ~] = size(A);
Steve has a much more in depth exposé of the problem and solution, and a follow-on post.
Instead of using ~, you could choose to use a junk variable and ignore it, but I (and Steve) prefer to use this relatively new feature and not
clutter the code or workspace with something that is a distraction.
Have you used ~ to ignore outputs from a function, or in a function definition to ignore an input? Let me know some details here.
Ever wanted to know if some points of interest were inside a region? You can answer that if the region is specified as a
polygon in MATLAB. The key is the inpolygon function.
Polygons in two dimensions are generally represented in MATLAB with two arrays, locations for the X vertices and Y vertices. There is no need to have the final points in these match the initial points; that is, when arrays as described
are used in situations where they are interpreted as polygon vertices, the polygon is automatically closed.
Previously, Jacob introduced the MATLAB code analyzer, mlint, which helps you write better code by notifying you of questionable constructs and opportunities for performance enhancement.
The code analyzer's messages are organized into categories, one of which is deployment. The deployment category contains 16 messages. Deployment messages are off by default; you activate them via code analyzer preferences. To help you make the best possible use of the feedback provided by the code analyzer, I'll use this week's posting to provide
an interpretation of each of its deployment messages. In the sections below, I quote code analyzer warning messages in italics.
Unsupported MATLAB Features
Some features of MATLAB do not work in deployed applications because of differences between the deployed environment and the MATLAB interactive environment. The MATLAB code analyzer warns about five such features:
MCC allows writing .m files, but they cannot be executed by the deployed application.
A MATLAB function may create another MATLAB function and then call it. For example, the Neural Network Toolbox uses this technique to train neural networks. A deployed application may create MATLAB functions on disk, but it cannot execute
them. Deployed applications only executeencrypted MATLAB functions and only MATLAB Compiler can create encrypted functions for deployment (MATLAB Compiler itself cannot be deployed).
Functions that create and then call MATLAB functions on disk cannot be deployed. If your code needs to create simple functions
at runtime, you may be able to use anonymous functions instead of creating new MATLAB function files.
MCC does not allow C++ files to be read directly using LOADLIBRARY.
When processing a C++ header file, loadlibrary creates new MATLAB function files. As discussed above, creating and then calling new MATLAB functions is a non-deployable
feature. As a result loadlibrary cannot be used with C++ headers in deployed applications. However, you can deploy applications that use MATLAB function prototypes with loadlibrary. (See the documentation for MATLAB Compiler; search for "loadlibrary".)
MCC requires the program to assign a value to output argument name .
When MATLAB Compiler processes a MATLAB function with outputs, it creates a wrapper function with output parameters. The generated
code requires that the output variables have valid MATLAB values when the function returns. MATLAB functions that do not assign
values to their outputs are likely to cause the program to crash.
MCC use of absolute file names is likely to fail.
MCC use of toolbox folder file names is likely to fail.
Deployed applications have a different view of the file system than applications running in interactive MATLAB. A deployed
application has a limited MATLAB path, and a different notion of the MATLAB root directory. A full discussion of this issue is beyond the scope of this post but, generally speaking, it is best to use relative paths instead of absolute
paths, and to avoid references to files in a MATLAB installation. If you need access to a file in MATLAB in a deployed application,
include the file in the application with the -a switch when creating it.
Unsupported Functions
MCC does not permit the function name function.
Certain MATLAB functions cannot be deployed because they rely on features of MATLAB that the deployed environment does not support. Avoid using these functions in code
you intend to deploy, or use the isdeployed function to ensure your compiled program does not call these functions. The code analyzer issues warnings about five unsupported
functions:
addpath: The path a deployed application uses to look for executable functions is fixed when the deployed application is created,
and cannot be changed.
help: The help database is too big to put in a deployed application. Besides, users of your application should not need help with
MATLAB functions, since your application encapsulates them.
keyboard: The implementation of this function relies on the MATLAB desktop environment, and deployed applications do not have access
to the MATLAB desktop.
savepath: Deployed applications do not support saving and loading the MATLAB path. The MATLAB path is embedded into a deployed application
when it is created, and the path can't be changed (so there's no point in saving it).
DEPLOYPRINT
MCC prefers Windows applications to call DEPLOYPRINT instead of PRINT, but use PRINT when printing to a file.
On Microsoft Windows platforms, a deployed application generates printed output by creating a JPEG file and then sending that
file to printer. This mechanism is very different from the way MATLAB prints on Windows platforms. Deployed applications must use the deployprint function on Microsoft Windows platforms.
WEBFIGURE
MCC requires that the first argument of WEBFIGURE not come from FIGURE(n).
MCC requires that the first argument of WEBFIGURE not come from FIGURE(n) (line number).
Deployed applications use the webfigure function to display graphics inside of a web browser. webfigure takes a single argument: the handle of a figure. Certain details of the implementation require that the figure's numerical
ID be automatically assigned by Handle Graphics rather than specified by the user. The code analyzer issues this webfigure warning when it detects code manually specifying figure IDs. For example:
f_ok = figure;
wf = webfigure(f_ok); % No warning generated
Functions with Unexpected Behavior
MCC use of the function name function is problematic.
The code analyzer generates warnings for the first two of these functions because they manipulate or rely on the program's
view of the file system, which is is very different in a deployed application. The third warning, about deployprint, only appears on UNIX systems. Deployed applications on UNIX systems print using print instead of deployprint.
cd: Changing the current directory in a deployed application does not affect the order in which the application will search
directories for executable functions. In fact, the current directory is never searched for executable functions.
matlabroot: In a deployed application, matlabroot refers to the root of the installed MCR against which the application is running. An MCR installation is not a full MATLAB
installation; applications cannot rely on being able to find all of MATLAB's functions or data files in an MCR installation.
deployprint: As noted above, applications deployed to UNIX systems use print instead of deployprint.
How do you use the code analyzer? Do these error messages make sense? Would you like to see the code analyzer integrated with
deploytool or mcc? Let us know here.
I’m pleased to introduce guest blogger Dave Foti. Dave has worked on MATLAB for over 15 years and currently manages the group
responsible for object-oriented programming features in MATLAB. He is interested in giving MATLAB users the tools to meet
increasingly complex challenges. This post will take a look at making use of object properties in MATLAB.
Properties are how MATLAB objects store data. At their most basic level, properties provide a way to define what data are
required for a particular kind of object. For example, if I have a set of measurements and each measurement has the same
pieces of information, then I can create a class of measurement objects with a property to store each piece of information
as in:
type surfaceTempReading1
classdef surfaceTempReading1
properties
Date
Latitude
Longitude
Temperature
end
end
The MATLAB documentation describes properties here.
Dependent Properties
In simple cases like this, it is probably fine to have all properties directly store and retrieve data. However, MATLAB provides
ways to define properties that don’t directly store data. These dependent properties are defined using the Dependent attribute as in:
type surfaceTempReading2
classdef surfaceTempReading2
properties
Date
Latitude
Longitude
Temperature
end
properties(Dependent)
Altitude
end
methods
function A = get.Altitude(reading)
A = lookupAltitude(reading.Latitude, reading.Longitude);
end
end
end
In this case, if I have a data set of surface temperature readings, I just need latitude and longitude to identify where the
temperature was sampled. However, in analyzing the data, it might be helpful to correlate temperatures with surface altitude.
Rather than have to input this data, the altitude can be calculated from a database of Earth surface topography. Assume
I have a function that can provide such a value called lookupAltitude, then I can invoke that function from the Dependent property called Altitude.
Dependent properties allow me some flexibility to implement the same external interface in different ways. A user of our class doesn’t
necessarily need to know how altitude was determined or whether or not it is actually stored in a class instance. This flexibility
can be useful in evolving a class over time while not breaking scripts and functions that might use the class. For example,
if I decide that TimeStamp is a better name for the Date property, I can gradually start switching over to the new name without immediately changing all of the code I have using
Date:
type surfaceTempReading3
classdef surfaceTempReading3
properties
TimeStamp
Latitude
Longitude
Temperature
end
% Deprecated property names
properties(Dependent, Hidden)
Date
end
methods
function D = get.Date(reading)
D = reading.TimeStamp;
end
function reading = set.Date(reading, D)
reading.TimeStamp = D;
end
end
end
When I change my class as above, not only will old scripts using Date continue to work, but old MAT-Files saved using the old class definition will automatically load the Date value into the new TimeStamp property. I use the Hidden attribute so that the old property name doesn’t show up in object display, the properties command, or tab completion.
t3 = surfaceTempReading3;
t3.Date = date;
disp(t3);
Dependent properties can also be useful any time a property has side effects – when for example changing a property triggers an update
to some other object or graphic or when getting a property requires doing some expensive operation to acquire or validate
the result. Often these expensive operations can be avoided from certain "trusted" code defined inside the class. Having
a one private property that doesn’t perform any side effects allows the trusted code to work on the raw property value. Other
code inside and outside the class can use a public and dependent property that performs the side effects or expensive operations.
Sometimes the expensive operation is just validating the input value being assigned to the property. For example, in our
class if I want to validate temperature values, I can do something like the following:
type surfaceTempReading4;
classdef surfaceTempReading4
properties
Date
Latitude
Longitude
end
properties (Dependent)
Temperature
end
properties(Access=private)
pTemperature
end
methods
function reading = set.Temperature(reading, t)
if t < 0
error('SurfaceTemp:BadTemp', ...
'Temperature must be a positive number in Kelvins.');
end
reading.pTemperature = t;
end
function t = get.Temperature(reading)
t = reading.pTemperature;
end
end
end
NOTE: The above example has been changed to correct an error in the original post.
Classes can define default values for properties. A default value is defined by the class and each instance of the class
is assigned that default value. Default values can be used when there is a constant default that can be documented with the
class definition. Default values can save space in MAT-Files because defaults are saved once per class and values of properties
not differing from default values don’t need to be saved. Generally speaking default values should be literal values wherever
possible so that it is clear what the default is. For example:
type surfaceTempReading5
classdef surfaceTempReading5
properties
Date
Latitude = '0N';
Longitude = '0E';
Temperature = 0;
end
end
While it is possible to use the result of a function for a default value, one should avoid doing so unless the function returns
a constant value. For example, it might be tempting to do something like:
type surfaceTempReading6
classdef surfaceTempReading6
properties
% Get the current date from MATLAB
Date = date;
Latitude
Longitude
Temperature
end
end
However, the problem with this is that the current date is not a constant default value that can be documented as part of
the class. Moreover, since MATLAB evaluates default property expressions in class definitions only when a class is loaded
or reloaded, the function call will generally happen once in a MATLAB session. Each object will get the same date stamp that
was current when the class was loaded and not the current date at the time an object is created (perhaps the next day). Generally,
one doesn’t want to assign a default value to a handle for a similar reason. If the intent is to make a new handle for each
instance, then this handle has to be created in the constructor and not as a default value. Since defaults are the same for
all instances created from a given class definition, all objects would get the same handle. For more information on handle
classes, see Handle and Value Classes.
I’ve described a few uses for properties and a few common attributes, but I would be very interested in hearing how you use
properties. You can post ideas here.
This week, guest blogger Jacob writes about how to use MATLAB-based tools to develop applications that are deployment-ready
from inception.
Deployed applications rely on the MATLAB Compiler Runtime (the MCR) for execution. The MCR differs from MATLAB in subtle but important ways. You will find it much easier to deploy
your MATLAB-based applications if you code with these differences in mind. You can learn how to develop deployable applications by reading our documentation and blog articles. To help you keep track of all the details, we're working on pushing some of this information into our development tools.
One of first tools we enhanced for deployment is the MATLAB code analyzer, mlint.
The code analyzer examines MATLAB code to detect possible problems or improvements. The code analyzer is integrated into the MATLAB Editor so you can see its suggestions as you develop your code.
Code analyzer suggestions are divided into several categories (you can fine-tune which messages are shown through the Code
Analyzer Preferences).
MATLAB Compiler (Deployment) Messages alert you when you use certain functions that may not deploy. However, you might not have noticed these messages before
since this category is disabled by default. In order to enable this category of messages:
In the Default Settings box, locate the MATLAB Compiler (Deployment) Messages category and click Enable Category.
Catching Non-Deployable Code
With Deployment messages enabled, the code analyzer can help detect when you are developing problematic code. For example,
Writing Deployable Code used the following as an example of code that may compile but yield undesired results at run-time:
cd mathFcns
z = add(x,y);
cd ../stringFcns
s = add(s1,s2);
In the MATLAB editor, the code analyzer highlights both instances of the cd command. By hovering your cursor over the underlined word, you view the warning message:
MCC use of the CD function is problematic.
Furthermore, if you click on the message, you get an explanation and suggested action. In this case, the suggested action
is to avoid use of the CD command.
Limitations of the Code Analyzer
The code analyzer can help catch many instances of non-deployable code. Most of these instances involve the use of known problematic functions like cd, addpath or help.
In fact, the Default Settings window in Code Analyzer Preferences displays all possible messages the code analyzer might display.
Reading these messages helps you understand what code constructs the code analyzer is likely to catch.
While the code analyzer is a useful tool for detecting some instances of non-deployable code, it cannot detect all instances.
For example, consider the following example which results in no warning or error message:
set(gca, 'ButtonDownFcn', 'LogButtonPress');
This code may result in a failure when deployed because MATLAB Compiler's dependency analysis (depfun) cannot detect that LogButtonPress is a function that must be included in the application. For this code to work in deployed mode, you must explicitly include
LogButtonPress at compile-time (by using the -a switch in mcc). In this case, the code analyzer suffers from some of the same limitations that MATLAB Compiler's dependency analysis does---the
inability to understand the contents of a string.
Use the Code Analyzer but Don't Depend on It
The code analyzer can help you to write deployable code, but it is not a substitute for understanding the compilation process
or how running your application in MATLAB differs from running against the MCR. This understanding ultimately provides the best foundation for writing deployable code.
However, even if you cannot completely depend on the code analyzer to guarantee deployable code, you can still use it to quickly
catch instances that might otherwise require lengthy debugging to correct. After all, problems caught while in development
usually cost much less to fix than problems caught when the application is deployed.
Are there other MATLAB coding patterns for which you think the code analyzer should issue deployment warnings? Let us know
here.
Have you checked out MATLAB Central lately? There's a new service called MATLAB Answers. It is a place where you can pose questions or search questions already asked to look for preferred solutions.
Recently there's been some fun activity on MATLAB Answers. The following thread is almost like a miniature MATLAB contest.
Check out the hump-day puzzler. And add your own solution there if you'd like!
I've recently been offered the opportunity to review a new book, The Elements of MATLAB Style by contributor to the FEX, Richard K. Johnson. It's a great opportunity for me to see what's important in the eyes of one particular prolific MATLAB user. And it's a
book worth you investigating for questions of style, especially if you work in a group or organization where there is lots
of shared code and lots of people looking at and using the code.
The first thing I like about Richard's book is the intent, to make it a reference in the venerable tradition of The Elements of Style, by Strunk and White. If you write in English, I highly recommend this book. Neither book is comprehensive but rather attempts
to boil ideas down to the ones with the largest pay-off and the ones where mistakes are often made. So you get some essentials
& pitfalls, and conventions (some, but not all, particular to MATLAB).
Taking a look at the table of contents, we see first some high level principles, followed by a small number of main topics:
Formatting
Naming
Documentation
Programming
Files and Organization
Development
with a few helpful lists bringing up the rear (e.g., keywords).
Each of these chapters ends with a summary section which pulls together the main themes of each section. These summaries
serve as a helpful review when you want to go back to look for more information. If it's listed there, you can be sure there
will be some items in the chapter to guide you.
I don't happen to agree with every choice Richard has made in terms of conventions, e.g., for layout or formatting. Nor does
MathWorks follow all of these (or all of any convention, in some cases). I do agree that he has identified relevant topics
worthy of any group embarking on a project to discuss and standardize on.
I'd now like to take a little time mentioning a few of many points from the book that resonate for me. These are only a sampling,
so don't read anything into ones that I have not listed here!
#7 Split Long Code Lines at Graceful Points - I find this one useful as it is a total pain having to trail far off to the right in any editor, even though it is possible.
# 10 Do Not Use Hard Tabs - This helps keep sanity when working among a group with possibly different editing environments.
# 43 Use Meaningful Names for Variables with a Large Scope - This makes code much easier to read, understand, and debug, if necessary.
# 69 Name Functions for What They Do - Since functions perform an action, the name should include information about the action.
# 86 Use Sortable Numbering in Data Filesnames - If you have many similar files of data, having a rational numbering scheme can only help you out.
# 97 Be Sure That Comments Agree with the Code - I will never forget the time that my thesis advisor called me because he was really irritated. I had left him a copy of
a Fortran program that had copious comments, the final one being "Ignore all the comments above; they were for a previous
version."
# 135 Avoid Cryptic Code - I have found that generally, writing cryptic code buys less than I expect in terms of good things, and more headaches than
it warrants. On occasion, I have used cryptic code for performance in something time-critical. When I do, I try to comment
it fully, including a straight-forward implementation in the comments which I have tested. That way, when the performance
trade-offs change, I understand what the code is supposed to do and have two starting options for doing a code update.
# 150, 151 Minimize the Use of Global Variables and Minimize the Use of Global Constants -- I would say this even more strongly myself. There are superior techniques for dealing with information you want to share,
whether they be function handles, classes and their properties, or some other methods. These techniques are much safer to
use for many reasons - e.g., more easily controlled side effects, should any be desired, and code becomes more suitable for
parallelism potentially.
# 172 Use Parenthese - Clarity of meaning is paramount, especially if others need to understand, modify, or translate the code.
# 176 Avoid Use of eval When Possible - I'm sure it doesn't seem so to some MATLAB users, but eval is avoidable most of the time.
# 185-188 The first of these is Avoid Complicated Conditional Expressions - These entries contain some useful thoughts on dealing with conditional constructs, the ordering of the cases, etc.
# 271-275 The first of these is Write Small Tests - I love that Richard has made testing a central tenet of this style guide. I don't see how programmers function well without
a robust test suite.
Congratulations to Richard for writing "The Elements of MATLAB Style." It's a book that I recommend you read. I encourage
you to adapt the guidelines in a way suitable for your programming environment.
You create a shared library or DLL to add MATLAB-based functionality to an application you're developing. You select one or
more MATLAB-based functions to include in the shared library, and MATLAB Compiler generates a binary file that you link against
your application. Shared libraries generated by MATLAB Compiler are compatible with the Microsoft Visual Studio development
environment on Windows and with the GNU C/C++ tool suite on most UNIX platforms. The list of supported compilers changes from one release to the next; be sure to check that list before starting your project.
Building a Shared Library
To illustrate the process of creating and using shared libraries, I'll use a cryptographic algorithm, the Vigenere cipher. The program I've written consists of two parts:
libvingenere: A shared library containing two MATLAB functions encrypt and decrypt.
vigenere.cpp: A C++ main program that calls the functions in libvigenere.
The source code for the MATLAB functions and the main program is available on MATLAB Central. The download package also includes VigenereDetails.html, which describes the implementation of the Vigenere cipher in MATLAB.
The mcc command invokes MATLAB Compiler both from within interactive MATLAB and at the system (DOS or UNIX shell) prompt. Use mcc to build a shared library from the MATLAB encrypt and decrypt MATLAB functions:
-W cpplib:libvigenere: Generate C++ wrapper code. Name the generated library libvigenere.
-T link:lib: Invoke a C/C++ compiler to create a platform-specific binary shared library file from the generated code.
encrypt decrypt: Place the encrypt and decrypt functions in the shared library. Generate C++ wrapper functions for each.
This command generates several files. Two of them are relevant here:
libvigenere.dll: The platform-specific binary: the shared library itself. On most Unix systems, this file ends with a .so extension: libvigenere.so.
libvigenere.h: Declarations of the C++ wrapper functions and C++ type conversion classes and utilities.
The Generated Interface
MATLAB Compiler generates many different kinds of functions: initialization, termination, error and print handling and, of course, the functions you selected to compile into the library.
In our example, MATLAB Compiler generates a C++ entry point for encrypt and decrypt. Stripped of some bookkeeping annotation, these functions look very much like the corresponding MATLAB functions.
The generated functions differ from the MATLAB functions in two significant ways:
The C++ functions explicitly declare the types of their arguments.
The C++ functions return void, passing back results in output parameters provided in the argument list.
Let's look at the encrypt function in detail. For comparison, here's encrypt's MATLAB function signature:
function ciphertext = encrypt(plaintext, key)
The encrypt MATLAB function has one output and two inputs. The encrypt C++ function has zero outputs (the void return type) and four inputs. The first C++ input indicates the number of outputs requested by the caller. As indicated by
the MATLAB function, the number of outputs may be zero or one. Passing any other value will result in an error. The second
C++ input is the output argument, passed by reference. encrypt will overwrite any data in this argument with the encrypted message. The third and fourth C++ input arguments are the function
inputs, the plaintext and the encryption key. They are passed by constant reference which means the encrypt function cannot change their contents.
Unlike MATLAB, C++ requires all variables have declared, immutable types. Variables in MATLAB have types as well (matrix,
cell array, structure, etc.), but the type of a MATLAB variable can change at any time. To accommodate this dynamic behavior
in C++, the MATLAB Compiler provides the mwArray data type. All the functions generated by the MATLAB Compiler take mwArray inputs and return mwArray outputs. The mwArray API allows you to create mwArray objects from most C++ data types and to extract native C+++ data from a returned mwArray.
Calling Functions in a Shared Library
Now that I've created a shared library, I need to write a program to call the library's public functions. The program performs
six tasks:
Creates input arguments; convert native C++ data types to MATLAB data types.
Invokes one or more functions from the shared library.
Shuts down the library and the MATLAB Compiler Runtime.
Below, I demonstrate how these steps translate into the code of the example's main program, vigenere.cpp.
Step 1: All programs that use a MATLAB Compiler-generated shared library must include the library's header file. The header file
has the same base name as the compiled library, libvigenere in this case, and a .h extension.
// vingenere.cpp: Encrypt and decrypt using the Vigenere cipher.
#include "libvigenere.h"
#include <iostream>
Step 2: The main program parses the command line. The first argument, a switch, determines the type of action: -e means encrypt, -d decrypt. The second argument is the message, and the third, the key.
int main(int ac, const char *av[])
{
// Encrypt or decrypt? Determined by command line switch
bool enc = strcmp(av[1], "-e") == 0;
Step 3: Initialize the runtime and start the library before calling any functions exported from the runtime or the library. Failure
to initialize will cause your program to crash. Always check for success (the initializers return false if they fail) and issue error messages as necessary.
// Initialize the MATLAB Compiler Runtime global state
if (!mclInitializeApplication(NULL,0))
{
std::cerr << "Could not initialize the application properly."
<< std::endl;
return -1;
}
// Initialize the Vigenere library
if( !libvigenereInitialize() )
{
std::cerr << "Could not initialize the library properly."
<< std::endl;
return -1;
}
Step 4: Convert the C++ strings from the command line (the message and the key) into MATLAB strings by creating mwArray objects.
These declarations cannot appear before the initialization calls in Step 3.
// Must declare all MATLAB data types after initializing the
// application and the library, or their constructors will fail.
mwArray text(av[2]);
mwArray key(av[3]);
mwArray result;
Step 5: Invoke the exported functions. Encrypt or decrypt as indicated by the command line switch. Note that the C++ functions have
the same name as their MATLAB counterparts, and that all return values must be passed in by reference. The mwArray class defines
// Initialization succeeded. Encrypt or decrypt.
if (enc == true)
{
// Encrypt the plaintext text with the key.
// Request one output, pass in two inputs
encrypt(1, result, text, key);
}
else
{
// Decrypt the ciphertext text with the key.
// Request one output, pass in two inputs
decrypt(1, result, text, key);
}
std::cout << result << std::endl;
Step 6: Shut down the library and the runtime, in the opposite order of initialization (library first, then runtime).
// Shut down the library and the application global state.
libvigenereTerminate();
mclTerminateApplication();
}
Creating and Running the Application
MATLAB Compiler uses the mbuild function to compile the code it generates into a shared library. mbuild knows how to invoke the C/C++ compiler with the correct switches so the compiler can find the required include files and
libraries. You can use mbuild to create your own executables and link them with MATLAB Compiler-generated shared libraries. On Windows, for example, issue
this command:
mbuild vigenere.cpp libvigenere.lib
On UNIX, you link against a .so file instead of a .lib file:
mbuild vigenere.cpp libvigenere.so
In both cases, mbuild produces an executable called vigenere.
Encrypt the message with the secret key.
>> !vigenere -e "Algebra, the Music of the Reason" "MATLAB"
MLZPBSM LSEAYUKTCA FSDHFLRXLSPZ
The first argument is the message, the second argument the key. Note the leading exclamation point -- this command runs the
vigenere executable from within MATLAB, using the system command. You can run these commands on the UNIX or DOS command line as well, but you have to configure your environment correctly.
Decrypt to verify the encryption worked:
>> !vigenere -d "MLZPBSM LSEAYUKTCA FSDHFLRXLSPZ" "MATLAB"
ALGEBRA THE MUSIC OF THE REASON
Because the alphabets in the Vigenere square only include letters and the space character, the decrypted message lacks punctuation
marks. Extending the algorithm to handle punctuation is an exercise left to the reader.
And extra points if you can figure out why I chose that phrase (aside from its poetic merit, which is in the eye of the beholder).
Next: Using Multiple Shared Libraries
I've shown you how to combine several MATLAB-based functions into a single shared library, and how to incorporate that library
into a host application. In a later posting, I'll demonstrate how to use multiple shared libraries from a single host application.
What else can I tell you about shared libraries? Let me know here.
Recent Comments