I have written some C extension before but it was pretty tedious. I have recently found another approach by using ctypes (http://starship.python.net/crew/theller/ctypes/). Which you develop your C module in dynamic library (DLL in Windows world), the from Python, you can call the C functions in the DLL using ctypes.
I have a library from Microsoft, ewfapi.dll, ewfapi.lib (not required), and ewfapi.h (see download) which I want to program the EWF capability in Windows XP Embedded. I was thinking about writing a Python C extension for it, but using ctypes is much easier. I only need to redefine some data structures from the header file, and not worry about common C tasks such as memory management, reference counting, etc. Ewfapi files can be downloaded from http://www.microsoft.com/downloads/details.aspx?FamilyID=eb3b3d35-ae95-4864-ba3c-d488d3980972&displaylang=en I have some sample usage in Python shown below, which I can interactively control the EWF feature using Python shell (in an XP embedded machine). # ewf.py import ctypes import string # These are the functions from the EWF API ##EwfMgrGetDriveLetterFromVolumeName(volumeName) ## ##EwfMgrVolumeNameListIsEmpty(volumeEntry) ## ##EwfMgrVolumeNameEntryPop(volumeEntry) ## ##EwfMgrVolumeNameListDelete ## ##EwfMgrOpenProtected ## ##EwfMgrClose = _ewfapiPy.EwfMgrClose ## ##EwfMgrClearCommand = _ewfapiPy.EwfMgrClearCommand ## ##EwfMgrSetPersistentData = _ewfapiPy.EwfMgrSetPersistentData ## ##EwfMgrGetPersistentData = _ewfapiPy.EwfMgrGetPersistentData ## ##EwfMgrCheckpoint = _ewfapiPy.EwfMgrCheckpoint ## ##EwfMgrRestore = _ewfapiPy.EwfMgrRestore ## ##EwfMgrDisable = _ewfapiPy.EwfMgrDisable ## ##EwfMgrEnable = _ewfapiPy.EwfMgrEnable ## ##EwfMgrCommit = _ewfapiPy.EwfMgrCommit ## ##EwfMgrCommitAndDisableLive = _ewfapiPy.EwfMgrCommitAndDisableLive ## ##EwfMgrCommitFile = _ewfapiPy.EwfMgrCommitFile ## ##EwfMgrSetLevel = _ewfapiPy.EwfMgrSetLevel ## ##EwfMgrGetProtectedVolumeConfig = _ewfapiPy.EwfMgrGetProtectedVolumeConfig ## ##EwfMgrGetProtectedVolumeList = _ewfapiPy.EwfMgrGetProtectedVolumeList ## ##EwfMgrOpenOverlayStore = _ewfapiPy.EwfMgrOpenOverlayStore ## ##EwfMgrGetOverlayStoreConfig = _ewfapiPy.EwfMgrGetOverlayStoreConfig ## ##EwfMgrRegisterLowSpaceNotification = _ewfapiPy.EwfMgrRegisterLowSpaceNotification # Short handle to the API ewfapi = ctypes.windll.ewfapi # Data structure from EWFAPI.h translated into Python # Map these enumerations to string EWF_CMD = { 0 : 'NO Command', 1 : 'Enable', 2 : 'Disable', 3 : 'Set Level', 4 : 'Commit', } EWF_STATE = { 0 : 'Enabled', 1 : 'Disabled', } EWF_TYPE = { 0 : 'Disk', 1 : 'RAM', 2 : 'RAM Reg', } # Forward Declaration pVolumeNameEntry = ctypes.POINTER('VolumeNameEntry') # Structure of a linked-list class VolumeNameEntry(ctypes.Structure): _fields_ = [('Next', ctypes.POINTER(pVolumeNameEntry)), ('Name', ctypes.c_wchar * 256), ] # Set the pointer to the structure ctypes.SetPointerType(pVolumeNameEntry, VolumeNameEntry) # Volume descriptor class VolumeDesc(ctypes.Structure): _fields_ = [('DeviceName', ctypes.c_wchar * 256), ('VolumeID', ctypes.c_ubyte * 16), ] pVolumeDesc = ctypes.POINTER(VolumeDesc) # Overlay configuration class OverlayStoreConfig(ctypes.Structure): _fields_ = [('FormatVersion', ctypes.c_ulong), ('VolumeSize', ctypes.c_longlong), ('NumSegments', ctypes.c_ulong), ('FreeSegments', ctypes.c_ulong), ('SegmentSize', ctypes.c_ulong), ('MaxVolumes', ctypes.c_ulong), ('NumVolumes', ctypes.c_ulong), ('MaxLevels', ctypes.c_ushort), ('VolumeDescArray', pVolumeDesc), ] pOverlayStoreConfig = ctypes.POINTER(OverlayStoreConfig) class Command(ctypes.Structure): _fields_ = [('Command', ctypes.c_int), ('Param1', ctypes.c_ulong), ('Param2', ctypes.c_ulong), ] pCommand = ctypes.POINTER(Command) class FileTime(ctypes.Structure): _fields_ = [('LowDateTime', ctypes.c_ulong), ('HighDateTime', ctypes.c_ulong), ] pFileTime = ctypes.POINTER(FileTime) class LevelDesc(ctypes.Structure): _fields_ = [('LevelName', ctypes.c_wchar * 64), ('LevelEndTime', FileTime), ('LevelDataSize', ctypes.c_longlong), ] pLevelDesc = ctypes.POINTER(LevelDesc) class VolumeConfig(ctypes.Structure): _fields_ = [('Type', ctypes.c_int), ('State', ctypes.c_int), ('BootCommand', Command), ('PersistentData', ctypes.c_ubyte * 32), ('MaxLevels', ctypes.c_ushort), ('ClumpSize', ctypes.c_ulong), ('CurrentLevel', ctypes.c_ushort), ('DiskMap_RamDataSize', ctypes.c_longlong), ('DiskDataSize', ctypes.c_longlong), ('MemMapSize', ctypes.c_ulong), ('VolumeDesc', VolumeDesc), ('LevelDescArray', pLevelDesc), ] def formatUnsigned(u): return '%02X' % u def unsignedArrayToHex(array): return string.join(map(formatUnsigned, array)).replace(' ','') def displayVolumeConfiguration(config, drive): config_type = EWF_TYPE[config.Type] print 'Type : %s' % config_type print 'State : %s' % EWF_STATE[config.State] print 'Boot Cmd : %s' % EWF_CMD[config.BootCommand.Command] print 'Param 1 : %u' % config.BootCommand.Param1 print 'Param 2 : %u' % config.BootCommand.Param2 print 'Persistent Data: %s' % unsignedArrayToHex(config.PersistentData) print print 'Maximum Levels : %u' % config.MaxLevels print 'Clump Size : %u Bytes' % config.ClumpSize print 'Current Level : %u' % config.CurrentLevel if config_type == 'Disk': print 'Disk Map Size : %u Bytes' % config.DiskMap_RamDataSize print 'Disk Data Size : %u Bytes' % config.DiskDataSize else: print 'RAM Data Size : %u Bytes' % config.DiskMap_RamDataSize print 'Memory Map Size : %u Bytes' % config.MemMapSize print 'Device Name : %s' % config.VolumeDesc.DeviceName print 'Volume ID : %s' % unsignedArrayToHex(config.VolumeDesc.VolumeID) print 'Drive : %s' % drive def information(): # Get the pointer and convert to linked-list node volume_list = VolumeNameEntry.from_address(ewfapi.EwfMgrGetProtectedVolumeList()) while 1: drive = chr(ewfapi.EwfMgrGetDriveLetterFromVolumeName(volume_list.Name)) print '%s: = %s' % (drive, volume_list.Name) handle = ewfapi.EwfMgrOpenProtected(volume_list.Name) config = VolumeConfig.from_address(ewfapi.EwfMgrGetProtectedVolumeConfig(handle)) displayVolumeConfiguration(config, drive) if ewfapi.EwfMgrVolumeNameListIsEmpty(ctypes.c_void_p.from_address(ctypes.addressof(volume_list))): break if __name__ == "__main__ ": print 'Running' information() -- http://mail.python.org/mailman/listinfo/python-list