When I wanted to use Python to call functions in Windows .DLL I was surprised that I had a difficult time locating the necessary information for making this happen. This is a base class that you use to define your class (and methods for each function). It uses Sam Rushings calldll, cstring and membuf modules but I think it will make interfacing with any DLL much easier for the beginner (especially for the first time).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 | # CLASS NAME: DLLInterface
#
# Author: Larry Bates
#
# Written: 08/14/2002
#
# Description: This is a base class for implementing a class interface
# to call general DLL libraries. You should build your class using
# this class as the base class. Define methods for each function of
# the DLL that you wish to implement.
#
import os, sys
import calldll
from dynwin.windll import cstring, membuf
class DLLInterface:
'''
class DLLInterface is used as a base class as a general interface class to
Microsoft Windows DLLs. None of the methods of this class should be
called directly. Subclass this class and have subclass' methods
make calls to _dllcall to call functions from the DLL.
'''
#--------------------------------------------------------------------------------------------
# Example usage:
#
# class anydll(DLLInterface):
# def function1 (self, arg1, arg2, ..., argn)
# #
# # code goes here to implement function1 from the DLL
# # as a method of anydll class.
# #
# # Syntax of _dllcall function is (function in .DLL,
# # argument types, ['llh' is long, long, short]
# # return code type, ['h' is short]
# # arguments in a tuple)
# #
# result=self._dllcall('function1',
# 'lll',
# 'h',
# (arg1,
# arg2,
# arg3,
# .
# .
# .
# argn))
# return result
#
# this would then be executed using:
#
# D=anydll(DLLPath)
# result=d.function(arg1, arg2, ..., argn)
#
# argument types = 'h'-short, 'l'-long, 's'-string (null terminated using helper function
# cstring in dynwin)
#--------------------------------------------------------------------------------------------
def __init__(self, DLLPath, ext='.dll'):
self._debug=0
self._trace=0
self._loaded=0
self._funcs={}
self._DLLName=os.path.split(DLLPath)[1]+ext # Save DLL filename
if self._trace: print "creating _handle"
#
# Load the DLL library (if not already loaded) and save a
# handle to it in self._handle
#
if not self._loaded:
self._handle=calldll.load_library(DLLPath+ext)
#
# If I didn't get a handle, DLL wasn't loaded
#
if not self._handle:
raise SystemError, "couldn't load module '%s'" % self._DLLName
else:
self._loaded=1
if self._trace: print "handle=",self._handle
if self._trace: print "Leaving __init__"
return
def unload(self):
if self._loaded and self._handle:
calldll.free_library(self._handle)
self._loaded=0
self._handle=0
self._funcs={}
return
def _dlladdr(self, func_name):
#
# This method uses the function name (func_name) and looks into the .DLL
# to find the address that should be used to call that function.
#
if self._trace: print "self._handle=",self._handle
if self._trace: print "_dlladdr to get address of %s func" % func_name
if not self._handle:
raise SystemError, "No handle found for %s" % self._DLLName
#
# See if I've called this func_name before. If I have, I have saved
# the address in self._funcs dictionary object so I don't have to call
# calldll.get_proc_address repeatedly. A method of "caching" the addresses.
# to hopefully speed things up a little.
#
try:
addr=self._funcs[func_name]
except:
addr=calldll.get_proc_address(self._handle, func_name)
self._funcs[func_name]=addr
if self._trace:
print "leaving _dlladdr, function %s has calling address=%i" % (func_name, addr)
print ""
#
# Return the address of this function so it can be called by calldll
#
if addr: return addr
else: raise SystemError, "%s has no function named '%s'" % (self._DLLName, func_name)
def _dllcall(self, function_name,arg_format_string, result_format_string, args):
#
# This method is used to make the call to the DLL function
# Arguments are:
#
# function_name - String containing the name of the function to call
# arg_format_string - this is a string that contains the format of the
# arguments that are to be passed to the function.
# These can be one of:
# l - long integer (or address)
# h - short integer (half)
# s - string
#
# Example: "lllh"
#
# result_format_string - The result will be either l or h, returned by
# function
# args - This is a tuple (even if there is only one argument)
#
# Example: (x,) or (a,b,c,d)
#
if self._trace: print "Entering _dllcall to call function=",function_name
result=calldll.call_foreign_function(self._dlladdr(function_name),
arg_format_string,
result_format_string,
args)
#
# If result_format_string is "h" mask out high bits of result
#
if result_format_string in ('h','H'):
result=result & 0xffff
#
# If result_format_string is "s", strip off trailing null character
#
if result_format_string in ('s','S'):
result=result[:-1]
return result
|
After about 2 weeks of trying to get Python to talk to a .DLL based toolkit that I wanted to use, I finally came up with a general solution to interfacing Python with .DLLs. This has been tested with ExperVisions RTK OCR toolkit and Castelle's CPI32 fax toolkit. I'm still a beginner, but I hope this saves someone some time/effort. It still takes some effort to figure out how to pass arguments (pointers vs values) and how to handle the structures some .DLLs employ, but at least this part of the problem is solved.
GREAT JOB--------Thanks!! Words can not express how much you have done for me with this code. Thank You
Another module for calling dll functions. You may want to look at ctypes from Tom Heller.
http://starship.python.net/crew/theller/ctypes/
Gene
Function Without Arguments. What do I have to do when my functions from DLL that don't have arguments?
result=self._dllcall("RevMensagens","","h",('')) ==> it doesn't work!!
Depricated. Today you are much better using ctypes (which is now part of the Standard Library) than this routine.