From NewWiki

FAQ Writing Packages


Question:
How do I need to layout my package?
Answer:
Writing Your Own Package - (Part 1 - Package contents and layout)

There are suggestions on how to write your own Mathematica package in the Mathematica Help Browser, on line at http://www.wri.com and in Roman Maeder's books on programming in Mathematica (http://www.mathconsult.ch/firma/firma-E.html#Pubs). You can write a package with almost any text editor, but the Mathematica FrontEnd is the ideal tool for this. If the package is to be of any substantial size, it is most conveniently written as a notebook, i.e., as a ".nb" file. But from this you can manually (using Save As Special) or automatically (if the notebook contains Initialization cells) generate a "package file", i.e., a ".m" file. The advantage of this is that the notebook version can break the text up into cells, with lots of comments, fancy formatting and inactive documentation sections, and these will be stripped out of the package file when it is written. The notebook should be written in "InputForm" as "StandardForm", (the default) misbehaves once in a while. You can force InputForm to be the default new cell form by setting the menu item Cell, Default Input FormatType to InputForm. When your notebook (for a package) gets big, and represents a lot of work, it is vital to practise defensive computing.

Mathematica allows saving packages as ".mx" files, using the DumpSave command. These are machine specific binary files so are not human readable. They load quicker than ".m" files, but are not portable across operating systems. There are issues with Contexts when using .mx format packages that can be troublesome.Also the loading of a ".mx" file cannot invoke actions (like the display of a startup banner,or playing your favorite tune). All it can do is load symbol definitions into memory.

Writing Your Own Package (Part 2 - Documentation)

The AuthorTools package described in the Mathematica Help Browser discusses how to produce documentation for your package that is accessible from the Help Browser and looks and feels like Mathematica's built-in help. This is a non-trivial task and to do it right can take about half of your project's total effort.

Writing Your Own Package (Part 3 - Protecting your IP)

If you are not concerned about intellectual property protection for the formulae in your package, than you can skip the next section. Most commercial software is distributed in executable form only - the source code is a closely guarded secret. Mathematica offers at least two mechanisms for doing this. Since the Help Browser documentation on this is brief, to put it kindly, here is more info.

The basic idea is to include commands at the end of your package which set the attributes of your "secret" functions to be ReadProtected, and then Locked. The ReadProtected means no one can see the function definitions, and the Locked means no one can undo the ReadProtected attribute.

It is probably not a good idea to also set the attribute Protected, because with Locked also engaged, your users will not be able to SetOptions on your functions.

The package file is still human readable and offers no protection from prying eyes. Saving the notebook as a package file in ".mx" format with the attributes set as indicated, offers protection from peepers, since the mx file is not human readable, but this option has some issues, mentioned above.

An alternative is to encode the package file with the Encode routine. This encrypts the package file, such that it is no longer human readable, but because it is an ASCII text file it is more portable. There is an exception to this portability - Linux encodes files differently from OS X and Windows.

The Needs or Get commands can read in the Encoded package file (possibly requiring a password, if you set one) and decrypt it, and once the package is in memory, the Locked and ReadProtect attributes now protect the secrets in your code. Here we give an example of this. We first show a trivial package that is written in a notebook, and saved as "demo.nb", for example. Since it's a tiny package it might contain only one cell, whose Cell Properties are set to "Initialization Cell". Here we assume the "secret function" we want to protect is the function "encrypt".

BeginPackage["demo`"]
encrypt::usage = "encrypt[string] hashes a string using the secret formula";
Begin["`Private`"]
encrypt[data_String] := Hash[data];
End[ ]
EndPackage[ ]

Here we test that the function does something.

encrypt["our test"]

1629761591

If we now load the package "demo.m" using Needs["demo`"] and ask for Information on encrypt we can see the entire definition of our formula, which would be bad, if this really were a secret.

??encrypt

 encrypt[string] encrypts string using the secret formula
 encrypt[demo`Private`data_String] :=  Hash[demo`Private`data]

So to protect our secret "encrypt" function, we now revise the package and set the Attributes.

BeginPackage["demo`"]
encrypt::usage = "encrypt[string] encrypts string using the secret formula";
Begin["`Private`"]
encrypt[data_String] := Hash[data];
End[ ]
SetAttributes[encrypt,{ReadProtected,Locked}];
EndPackage[ ]

If we now ask for Information we can not see the function definition.

??encrypt

encrypt[string] encrypts string using the secret formula
Attributes[encrypt] = {Locked, ReadProtected}     

Next we encode the package file.

Encode["demo.m","demoe.m"]

We list the encoded package "demoe.m" and see it is not human readable.

!!demoe.m

(*!1N!*)mcm jE2FtTGjEmi2X^Ue>E2FtTGjEmi2X^Ue>E2FtTGjEmi2X^Ue>E2FtTGjEmi2X ^Ue>E2FtTGjEX4*4+5]HauE~i-SJ/_kQNyL<(=NQi"dYNZ'Skk425[0X&lF93l'"9_jYJ5 BEX2=mcUTP6@oXt~$/27,yoERZ\Q'iG~ V[P]sD[MV18XdLd6`?e(YGbd}9IE"<8a/naAPi[m)LEh:8V;GkuZM2T6(NoE,t&HSoVlSK>\>GLLh3X1 N^[$D?IV_>r(qhVIsIu*UYJ%=bt"OejKcz.1ae;/F"Rk^,0rt{&Hb\Ii7la9O9bCo[BE2FtTGjEmi2X^Ue>E2FtTGjEmi2X^U e>E2FtTGjEmi2X^Ue>E2FtTGjEmi2X^Ue>E2FtTGjEmi2X^U\mh>>XD/ZG]2h>>XEP`AnS fMp,0(K}6Uh9L,.GSY(Vkz.h&2ba)rSK^j_K8x?!t=$V9lOF5l&,95HB8ht= NOq9y$+h3 NH_/EmoNkx,cK|p}?.1"U{"#>XD/ZG]2h>>XD/ZG ]2h>>XD/[809

But it loads in like any other package.

Get["demoe`"]

and the function works as before

encrypt["our test"]

1629761591

and we can't peek inside the function definition.

??encrypt

encrypt[string] hashes a string using the secret formula
Attributes[encrypt] = {Locked, ReadProtected}

Any attempt to change the Attributes or the function fails. So your secret formula is protected - to the level provided by Encode. So "demoe.m" is the "executable" file that we will actually distribute to our clients along, with its Documentation folder, and we hold the notebook file "demo.nb" as our closely guarded "source" code.

Writing Your Own Package - (Part 4 - License duration control)

Having a package only function for a prescribed period of time, is easy to implement. Just use the Date routines to compare current date with some "expiry date".Of course this expiry date must have the Locked attribute set as described above, and the expiry control routine must run when the package is loading, hence the .mx file format for a package can't implement this.

Here is a simple example of how you might do this. In your package you could include a symbol "your$LicenseExpirationDate" which sets the date and you must set the Protected and Locked attributes on this symbol after setting its value.

your$LicenseExpirationDate::usage="your$LicenseExpirationDate returns the date 
of expiration of your package's licence";

your$LicenseExpirationDate={2006,0,0,0,0,0};  (* the expiry date for this licence *)
SetAttributes[your$LicenseExpirationDate,{Protected,Locked}];

Then early in your package you include something along the lines of following bit of code:

If[FromDate[Date[]]>FromDate[your$LicenseExpirationDate],
Print["This session has been terminated because your licence has expired. Have a nice day."];
Exit[],
Print["Your licence is valid until ",your$LicenseExpirationDate]];

If you think the Exit[] is too rude, you can substitute some nicer response.

Writing Your Own Package - (Part 4 - License Passwords)

Can anyone contribute ideas on convenient methods to have a package consult a Licence password stored in a file, before running, just like Mathematica itself does?

Contributors to this Page The 2 contributors to this page (ordered by date of first contribution):
User Latest Contribution # Contributions
1. Christopherpurcell Thu 6 Dec 2007 16:56:11 5
2. LucB Tue 3 May 2005 11:37:38 1

This page was created by Christopherpurcell on Sat 2 Apr 2005 00:41:28 and last updated by Christopherpurcell on Thu 6 Dec 2007 16:56:11
Retrieved from FAQ Writing Packages .
Personal tools