wiredfool

Author Archive

Fun with SWIG, wxPython, and the Windows event system

One of the things that I do at the day job is write support for various models of check scanners into our scanning application. It’s a python app, running on Windows using wxPython for the interface. And the one constant in the whole thing is that no two scanners work alike, connect similarly, or have remotely similar APIs. So far, I’ve done:

– Serial
– Serial protocol over Ethernet
– XML over HTTP
– COM Based
– COM Based with Event Callbacks
– SWIGified dll interface
– SWIGified dll interface, with Event Messages

The last scanner that I worked on (which shall go unnamed due to NDA (and really, it’s a published API. Why an NDA? (It’s not like people developing for your scanner wouldn’t like it if everyone copied the same interface))) was the most involved so far, at least to the point of getting the first image out of it. After that, it actually was pretty simple. (And to be fair, there is something called the Ranger API, which does support a good number of scanners, but not all of the ones that we’re interested in. It’s up there, under COM with event callbacks).

Step 1: Getting a SWIG wrapper of the dll to compile using Visual Studio .NET 2003. I’m using VS.net 2003 since I have to stay with what compiled Python 2.4. So, it’s not modern, but it works for what I need it to do. There are a lot of little bits to getting a working SWIG wrapper, especially with debug mode. I gave up on a full debug version of this one due to the difficulty of building a debug version of wxWindows/wxPython on top of all the other python modules that I’d need. First thing is to download SWIG and any other dependencies. I’m on the 1.3 tree of SWIG, later versions may differ. You need to start with a dll project, add the appropriate headers and whatnot. The python libraries and the driver libraries need to be available for linking, the output needs to be put in a \_{module}.pyd file (or
\_{module}\_d.pyd for the debug version). There needs to be a SWIG .i interface file with a custom build step of:

swig.exe -python -o “$(ProjectDir)\$(InputName)_wrap.cxx” “$(InputPath)”

with an output of “$(ProjectDir)\$(InputName)_wrap.cxx”

A minimal .i file for wrapping a windows dll:

%module XVX
%{
/* Includes the header in the wrapper code */
#include “stdafx.h”
#include “XXinterface.h”
%}

/* Parse the header file to generate wrappers */
%include
%include “XXinterface.h”

This .i should swigify and compile, but is not the most useful thing in the world. I had trouble linking, even though all the files to be linked were available. I finally tracked it down to the calling convention — where the last SWIG dll wrapper I made used fastcall, this one required cdecl.

Step 2: Getting a usable hWnd reference from wxPython to a SWIG wrapper so that it worked. The window handle as returned from wxPython’s window.GetHandle() is a python int, which SWIG doesn’t like to automatically convert to a hWnd. So, there’s a little typemap magic in the swig interface file to take that Python integer and turn it into something usable.

/* handle hwnds */
%typemap(in) (HWND Handle) {
$1 = (HWND) ((int)PyInt_AsLong($input));
}

It’s a little ganky in that I’m taking a random integer and making it a window handle, but looking at all the typedefs, I’m pretty sure that it’s a valid approach. What I’m not 100% sure of is if this will work on 64bit machines. I reserve the right to revisit this when I have a 64bit test machine with dev tools.

Step 3: Hooking the Event system so that we could catch ON_MESSAGE events.
The sample code I have is for a MFC C++ app, and it has a message map:

BEGIN_MESSAGE_MAP()
ON_MESSAGE(CUSTOM_EVENT,myHandler),

END_MESSAGE_MAP()

It turns out that while wxWindows/wxPython does get most events (mouse, command, menu, etc) and allow them to be handled by registering a handler, the ON_MESSAGE event is not one of them. The messages come into the application through a WndProc. The only reference I found in google for this was a faq page which references a MSWWindowProc that you have to override. That didn’t appear to work, which led to this list message (which is archived at a few places on the web, but on devshed.com, it doesn’t have the all important link to the answer) that links to code for overriding the WndProc and getting all the messages that you need. Once you have that, it’s a simple matter of filtering for the message type sent by the driver.

Step 4: Fleshing out the SWIG interface so that it’s not quite as painful to use. There are a lot of methods that pass back short strings in a buffer that you provide. That’s easily handled using a typemap pair in the .i file. This fragment will take the char* outString, BYTE MaxLen pair, wherever they appear, and drop them from the required python arguments of the function, and append them to the result. It could be a bit better, in that it returns all 255 characters from the buffer and it returns an array of [boolean, string] to python. I’m still working on a fix for that.

/* handle the strings */
%typemap(in,numinputs=0) (char* outString, BYTE MaxLen)(char s[255]) {
$1 = s;
$2 = 255;
}
%typemap(argout) (char* outString, BYTE MaxLen){
$result = SWIG_Python_AppendOutput($result, SWIG_FromCharPtrAndSize($1,$2));
}

I tend to target named parameters, rather than target any type combination like char*, BYTE. It’s easy enough to apply this to other names:

%apply (char* outString, BYTE MaxLen) { (char* ErrorString, BYTE MaxLen) };

Next, the ON_MESSAGE event has two parameters, a message and one that’s either a pointer or an int. Since that pointer is delivered directly to python without being able to typemap it to something else, I’ve added a couple of convenience methods for getting the contents of that pointer. (without pulling ctypes into it) The typemap does something similar to the hWnd typemap above, and the inline function just returns my input, but SWIG will take that pointer and turn it into the python representation of that structure.

%typemap(in) (ImagesStruct *pImageStruct) {
$1 = (ImagesStruct *) PyInt_AsLong($input);
}

%inline %{
ImagesStruct * WINAPI _GetImageStruct(ImagesStruct *pImageStruct ) {
return pImageStruct;
}
%}

No comments

Pizzicato

Vizzicato

No comments

Hummingbird with a 50

Hummingbird with a 50

No comments

Fashion Model

Fashion Model

No comments

Updating Ubuntu, Part 2

I’ve also just updated another one of my ubuntu machines, the netbook, to the latest 9.04 netbook remix that was released yesterday. It had been running an 8.10 eeebuntu release that had some issues. It’s main issue was that it didn’t like waking up from suspend with the GIU intact. Normally, it required killing X and restarting it, which is about as disruptive to working as rebooting the whole machine.

This time, I didn’t bother with an update, it was a clean install on a different SD card. That makes it easy to go back to the previous install by rebooting ad switching the cards. Though, it meant I had to spend another $12 for an 8 gig card.

It appears that all the hardware of my 901 is recognized: the wifi, ethernet, camera, bluetooth, and the USB760 3g dongle. (though, I still have to do a little patch to prevent the dongle from showing up as a drive first). And, most importantly, the suspend and resume sleeping works again.

I could still go into the many ways that this netbook is not an apple product, and I still probably will. But, it does web, email, and ssh, with the occasional reboots into windows to deal with windows specific work stuff.

No comments

Updating Ubuntu

On of my main linux machines was running Ubuntu 6.06LTS, which is a long term support release from the middle of 2006. It was getting a little long in the tooth (firefox 1.5 anyone?) and that was getting tiresome.

So yesterday, I bit the bullet and did the upgrade to the newest long term support release, from last spring. Following the directions worked well enough, except for a couple of packages in the openoffice 2.4 release that I had installed. There were a set of them with circular dependencies, so they couldn’t be removed, which in turn were blocking a newer bugfix of openoffice 2.4, in turn, that was blocking the package manager from doing anything useful like updating emacs from version 21 to 22.

Apt is a good package manager, but sometimes it gets into states that aren’t easily resolved. If you get conflicting messages about something being installed, that’s a good sign that you’re there.

The normal solutions didn’t work :

sudo apt-get -f install
sudo apt-get -f remove
sudo apt-get dist-upgrade

Were all hopeless.

What finally worked was downloading two upgraded packages directly (libhsqldb-java adn openoffice.org-base) and installing them manually via dpkg, and then clearing out all the circular references with:

sudo dpkg -r openoffice.org-kde-integration
sudo dpkg -r –force-all openoffice.org-core01
sudo dpkg -r –force-all openoffice.org-core02

Dpkg can force things that apt-get can’t, or won’t do. After that, sudo apt-get upgrade -f dist-upgrade was enough to make everything work properly.

Finally, there’s a package archive for the shiny new openoffice 3 packages, but it takes some digging to find the archive key and the keyserver.

##repo for open office3
deb http://ppa.launchpad.net/openoffice-pkgs/ubuntu hardy main
deb-src http://ppa.launchpad.net/openoffice-pkgs/ubuntu hardy main

gpg –keyserver keyserver.ubuntu.com –recv-keys 60D11217247D1CFF
gpg -a –export 60D11217247D1CFF | sudo apt-key add –

No comments

Outside

I spent most of the day outside on the first day in the last 5 that hasn’t been a basically perfect spring day. We had an arborist over taking down 11 trees that were either threatening, damaged, or blocking much needed sunlight. They ranged from little (3″ dia) but hung up in others to downright huge (2′ dia). All of them are about 35 years old, as most of the other trees on the property are.

Sometimes, when the wind was right, the sawdust drifted down from the treetops and the breeze smelled of christmas trees. Then a 20 foot treetop would plummet and slam into the ground.

No one was hurt, not even the little japanese maple that was less than a foot from a couple big drops. This is why we brought in the professionals.

And finally, we’re seeing sprouts from the plantings from last week — the spinach, lettuce, radish, and beets are all coming up.

No comments

And now for the early April Planting

It was 70 in the shade on the sunny side of the house, and 65 in the shade on the north. This is the first day that it’s been warmer outside than in. And 2 days straight of eating outside for lunch and dinner.

Now we get to the high volume stuff. There’s chard. And half a bed of kale to fill out the bed that didn’t quite make it through the winter. (What do you know, dwarf siberian kale overwinters better than nero de toscano. I guess it’s not so cold in Tuscany). Nevada is now half shelling peas and half favas, and the former compost pile is now an extension to that bed and has transplanted wild strawberries (that were happily colonizing the compost pile) a couple lines of sweet peas, and some dalias. The sprawly bed is also worked over, and what isn’t in (not-wild) strawberries and garlic is now 8x 20+foot rows of snow and snap peas, at least until I need it for sprawly things. It actually looks like a standard set of garden rows now.

I’m going to be sore tomorrow. Clearing the sprawly bed was a lot of work.

And on top of that, we planted seeds for starts. 2 types of onions (Guardsman and Candy), leeks, cauliflower, cabbage, 2 brussel sprouts (Franklin 80 day and Diablo 160 day), eggplant, bell peppers (red green and yellow), basil, pumpkins (small saved, big saved, and magic lantern from a packet), sunflowers ((king) kong, saved), coriander, parsely, celery, and tomatoes (free, came with the greenhouse).

Still to plant in pots, probably in a month or so, are the rest of the squashes and the cucumbers, another planting of some of the brassicas, and probably more basil and coriander/cilantro. And whatever else seems like it needs a start in a greenhouse.

(And really tasty, a pestoish mixture of basil, cilantro, serrano pepper, and olive oil. With a bit of salt. It’s gooood. )

No comments

End of March Planting

Got some of the end of march planting done — one bed of beets and one bed of mixed salad stuff: radish, salad blend, and two varieties of spinach. There’s still some more peas and some chard to plant before I’m done for now.

Interestingly, the soil temperatures in the earlier pea beds are below where they were when I planted almost a month ago. (High 40’s then, 46-48. They’re now 43-46) The peas are just starting to show, but the favas in the main garden aren’t doing anything yet. The favas off in Nevada (well, that’s the shape of the bet) are starting to sprout now, so I guess that gets a bit more light and heat. It’s been a cold March, last year we has more stuff up by now, and the salad bits were planted two weeks earlier. Then of course, last year it Snowed in mid April, so maybe we’re not that behind.

No comments

Things I’ve noticed about the new iMac

It’s running leopard, and it’s new, fast and all that. Which is all different from what I’ve had before.

– It’s fast. It’s amazing what going from 2.5 yr old laptop tech to current desktop tech will do, even if I didn’t get a quad core in it. And 2×24″ monitors is nice for programming.

– The screen is not as good as my Dell 2407WFPHC, even when calibrated. There’s a distinct shift to the color cast of the backlight from side to side, and the backlight intensity varies as well. It may be a subtle angle thing, I’m not sure I can tell. I’m also not getting it to be anywhere near as warm as the calibrated Dell, even when I’m using the same target profile for both monitors.

– Waking the external display from sleep goes to static. It’s the first time I’ve seen a machine snowcrash.Even if it does just mean that I have to powercycle the display.

– Fast user switching and terminal and multiple monitors don’t play well together. All the terminal windows end up on the main display when switching back. Maybe I should just use xterms, since they don’t have the same problem.

– iTunes stops playing when I swap users using fast user switching. PITA when I just want to check my mail. Also, I can’t keep a phone call on gizmo through switching users. What I’d really like to do is dedicate one ‘space’ to each user, and just switch without login issues and such. Not sure that’s possible though.

– I can’t control the headphones and the speakers separately. I’d love to do something complicated to the sound routing like: Alerts-> speakers. Incoming Phone call rings -> both. Music -> switchable. But most importantly, incoming phone rings always to the speakers, no matter what, so that I can hear it if I’m not at my desk. And it’s not like it’s exactly easy to find the headphone jack, since it’s behind the computer.

No comments

« Previous PageNext Page »