create blog

go home go home
  1. about
  2. code
  3. wiki
  4. blog

Archive for the ‘Script’ Category

Python, Windows, and Network

Thursday, April 16th, 2009

We have several machines. All of them (except for mine, a MacBook Pro which I use for almost everything) run Windows.

I’ve been learning Python. It is a really useful language. It runs on the command line, and that is really important. If I could, I’d use JavaScript instead, but some things — such as connecting to MySQL servers — are a bit much for me to write JavaScript shells for at the moment (especially because it has been a year or three since I’ve dealt with the C++ MySQL APIs).

So, for a recent diversion which required MySQL database access, I decided to use Python. If I can remember, I’ll write about the project later. It was a simple script to keep track of sequence numbers for the new Intelligent Mail Barcode, so that we could ensure each piece had a unique number in any 45-day period.

Windows does not come with Python pre-installed. This is not usually a problem, as Python is not at all difficult to install. But in addition to having to install Python, I’d have to install the Python package for MySQL. This Python script could be used from several computers, so I’d have to do in on each computer. Even if I posted an article on our intra-office wiki (which it still seems like nobody reads), I would probably have to end up helping everyone install it.

And, what if I make a mistake? Having so many installations (at least 3 or 4, possibly more, and prone to change whenever we replace or add a computer) could make me very busy with things I don’t really want to be busy with.

What would be best is if I could install Python on a central server. Well, I couldn’t do that, but I could install Python on my Windows computer (which, alas, I still have to use sometimes), and figure out what I needed to copy to the server.

It is really quite simple in principle: just install Python on Windows. Copy C:\Python25 (or whatever your Python install directory is) to your central server.

Except… it still won’t run on the other computers.

It complains about missing a Python25.dll. It would seem that the Python installer was stupid enough to not install its DLLs in the install folder along with Python itself, but instead litter the already-overpopulated C:\Windows\System32 directory with them.

So, I found all of the DLLs that looked like they belonged to Python 2.5, and copied them into the Python25 directory on the central server:

  • python25.dll
  • pythoncom25.dll
  • pywintypes25.dll

Could I have missed some? Perhaps. But everything appeared to work.

I still had one complication: it would be nice if scripts could run without the command needing to say r:\path\to\Python25\python. For this, each computer would need to have Python’s path in their PATH system variable.

Instead of adding yet another item to PATH, however, I decided to make a simple command file that would “initialize” Python by adding it to the instance’s PATH. This would only last the duration of the Command window.

Here is the script, changed only slightly:

@echo off
 
IF "%INITIALIZED_PYTHON_25%"=="YES" GOTO END
 
SET PYTHONPATH=R:\path\to\python\python25\
SET PATH=R:\path\to\python\python25\;%PATH%
SET INITIALIZED_PYTHON_25=YES
 
:END

And that’s it. As the script I was working on (and likely any others in future) would be run from batch files anyway, they’d just need an extra line at the beginning to call this command. And that’s it.

Script & the USPS Intelligent Mail Barcode

Monday, March 16th, 2009

We need a way to integrate the new USPS Intelligent Mail Barcode nicely into our existing workflow. The software we use for most of our composition seems to have some… disagreements (or something)… with it at times, even though it officially supports it.

Other people using the same software recommend using the USPS’s library. That’s fine and all, but we don’t want to write a C program for each job — writing in C or C++ can be quite time consuming. And it requires compiling, creating projects, etc. In short, a lot of hassle.

While this may not be the course we end up following, I decided, tonight, that although I was half-asleep, I’d attempt to add scripting support for USPS’s library. At around 10:00, I downloaded the software from USPS. Now, roughly fifty minutes later, I have managed to write a script that uses the USPS barcode.

(more…)

v8, Application Exit, and Destructors

Friday, February 20th, 2009

While working on a utility that may perhaps evolve into the next version of the Engine, written primarily in JavaScript, I ran into a small problem when I tried to wrap output files for use in JavaScript.

v8, when it “goes away” at program end, does not collect its garbage. Not usually a problem, as most of the time, the operating system will clean up after you. But I didn’t need the memory cleared. I needed a destructor called.

The output file wrapper was wrapping a class which wrapped ostream. The standard library stream usually uses a buffer, and only calling flush() or destroying the stream flushes it to the actual output. I needed this to happen automatically, so I wrote up a simple template class, AutoDestroy, along with a helper function, autoDestroy.

(more…)

Interesting Bug #1: The Case of the Sticky Object

Monday, February 2nd, 2009

In my post on persistent handles, I mentioned that it is good to keep a map between native C++ objects and their JavaScript wrappers, so that you can reuse the wrappers.

I also mentioned that I clear V8′s reference to the native object when C++ “forces” a destroy.

Everything worked, except one thing: when I cleared the reference to the native object, I did not clear the reference from the map. Lo and behold, at some later point in time, when such an object is created again, the pointer to the original is still in my map. So, when I ask the map if a wrapper exists, it does. And its reference is NULL. So, I just passed a non-NULL object to JavaScript, and JavaScript got a NULL value.

All I needed to do to fix it was add a std::set of things to alert to the clearing of the reference, add the map-containing object to that set, and call a function which erases the entry in the map-containing object when the reference is cleared.

It is quite lucky for me that this bug occurred. It occurred due to an unintended consequence of normal object destruction. Accidentally, when the object was destroyed even through a process initiated from JavaScript, the “force destruction” message was sent out. Had this unintended side-effect to destruction not been there, I would not have noticed anything, and some wacky consequences of reusing wrappers for unrelated objects could have been extremely difficult to debug.

A bug a day keeps the doctor away?

The Script Engine

Saturday, January 31st, 2009

One of the components of the framework on which I have been working particularly hard in the past week is the Script Engine.

It is what it sounds like: a module designed to allow scripting to work inside the framework. Although most definitely still a work-in-progress, it now has a lot of the features I want it to have.

My goals were:

  • It should be extremely easy to make an object scriptable (less than ten minutes)
  • It should be extremely easy to pass objects to JavaScript
  • It should be extremely easy to retrieve objects from JavaScript
  • It should be possible to implement other scripting languages in future

I don’t know about the last, as I haven’t tried it yet, but the first three I think I may have succeeded in to some extent.

Basically, to give you the idea of what it does, I’m going to give a code dump showing how the script engine works. You very likely will not be interested. On the other hand, you could. So, I am posting it.

(more…)

Persistent Handles

Saturday, January 31st, 2009

You probably don’t like memory leaks. I don’t. But, if you have one object that needs to pass between two languages — C++ and JavaScript — each of which may keep that object indefinitely, it can become tricky to make sure that any given object is destroyed, and that it is destroyed at the right time.

There are two things that can happen: an object can be deleted two soon, while it is still being used elsewhere — causing some particularly delicious crashes — or, an object can be deleted too late (or not at all), causing memory leaks.

(more…)

V8 Objects

Thursday, January 29th, 2009

So, a problem arose.

I wanted to account for two possibilities in the Script Engine: Passing existing objects from C++ to JavaScript, and creating new C++ objects from JavaScript. The act of passing a native object into scripting languages is usually referred to as wrapping (although, at one point inside the engine, I actually refer to a part of the process as unwrapping).

The code I would like to be able to use is:

//create a point
Point *point = new Point(.42, 42);
 
//pass it to some JavaScript function
myJavaScriptFunction->Call(pointWrap(point), 0, NULL);
//create a Point
var point = new Point();
 
//set its X value
point.x = 4.2;
 
//call some C++ function using it
myCPPFunction(point);

So how did I manage this in the engine? Well, as I am prone do, I overcomplicated it.

(more…)