Code to call a Windows Dll """void FAR PASCAL hllapi(int FAR *, char FAR *, int FAR *, int FAR *)""" with ctypes (trivial) and calldll (a nightmare).
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 | # PROGRAM NAME : HLLAPI interface - ctypes version
# Author: Stefano Spinucci
# Written: 2002/02/16
# DESCRIPTION
# This program interface the 3270 HLLAPI library of an Italian 3270 emulator using
# the ctypes library (home page : http://starship.python.net/crew/theller/ctypes.html
# or on sourceforge : http://sourceforge.net/projects/ctypes)
# The calling scheme for the function is :
# void FAR PASCAL hllapi(int FAR *, char FAR *, int FAR *, int FAR *);
# NOTE :
# <from ctypes docs> Internally ctypes makes heavy use of the new type system introduced
# in Python 2.2, so it will not work in earlier versions.
from ctypes import windll, c_int, c_string, c_char_p, byref
# ------------------------------------------------------------------------------------------------
# dll initialization
# ------------------------------------------------------------------------------------------------
#Load the dll 'Ehllapi.dll' (the file .py is in the same directory of the dll)
Ehllap32 = windll.ehllap32
#Load the function 'hllapi' from the dll
hllapi = Ehllap32.hllapi
# ------------------------------------------------------------------------------------------------
# variables setting and function calling
# ------------------------------------------------------------------------------------------------
#Set the variables
h_func = c_int(1)
h_text = c_string('A')
#alternatively to "h_text = c_string('A')" you can use "h_text = c_char_p('A')"
h_len = c_int(1)
h_ret = c_int(999)
#Function calling
hllapi(byref(h_func), h_text, byref(h_len), byref(h_ret))
#Print the value returned
print h_func.value
print h_text.value
print h_len.value
print h_ret.value
# PROGRAM NAME : HLLAPI interface - calldll version
# Author: Stefano Spinucci
# Written: 2002/02/16
# DESCRIPTION
# This program interface the 3270 HLLAPI library of an Italian 3270 emulator using
# the calldll library (from Sam Rushing http://www.nightmare.com/software.html)
# I've found very useful also edll.py from http://pages.ccapcable.com/lac/undergroundPython.html
# The calling scheme for the function is :
# void FAR PASCAL hllapi(int FAR *, char FAR *, int FAR *, int FAR *);
# ------------------------------------------------------------------------------------------------
# Function defining :
# - myPrintLong : given a membuf with a long inside, print the long
# - myPrintString : given a membuf with a string inside, print the string
# - mySetLong : given a membuf with len = 4, set his value with the long passed
# - mySetString : given a membuf, set his value with the string passed (adding the character \0)
# ------------------------------------------------------------------------------------------------
def myPrintLong(vVar):
#Print the long (first way)
a= struct.unpack('I', vVar.read())[0]
print a
#Print the long (second way)
print calldll.read_long(vVar.address())
def myPrintString(vVar):
#Print the string (first way)
a = vVar.read()
print a[:len(a)-1]
print len(a)
#Print the string (second way)
a = calldll.read_string(vVar.address())
print a
print len(a)
def mySetLong(vMemBuf, vValueToSet):
string_packed = struct.pack("L",vValueToSet) # packed as unsigned long
vMemBuf.write(string_packed)
def mySetString(vMemBuf, vValueToSet):
data_len = len(vValueToSet)
pack_format = str(data_len+1)+"s" # add one for \0 at the end.
string_packed = struct.pack(pack_format, vValueToSet) # pack() will add \0 for us
vMemBuf.write(string_packed)
# ------------------------------------------------------------------------------------------------
# Import the required library
# ------------------------------------------------------------------------------------------------
#Import the calldll module
import calldll
#Import the struct module (a standard python module)
import struct
# ------------------------------------------------------------------------------------------------
# Get the handle of the dll and the address of the function
# ------------------------------------------------------------------------------------------------
#Get the handle of the Dll
handle = calldll.load_library ('C:\Tee3270\Ehllap32')
#Get the address of the function
address = calldll.get_proc_address (handle, 'HLLAPI')
# ------------------------------------------------------------------------------------------------
# Initialization
# ------------------------------------------------------------------------------------------------
# vFunction, vTextLen and vResult are defined as a membuf with lenght = 4, because 4 is the lenght
# of an unsigned long packed with struct.pack("L", NumberToPack)
vFunction = calldll.membuf(4)
vTextLen = calldll.membuf(4)
vResult = calldll.membuf(4)
# vFunction is defined as a membuf with lenght = 1921 because the dll needs a buffer of
# 1920 char + 1 for \0 at the end
# You can here define a membuf of the lenght you need + 1 for the last \0 character
vText = calldll.membuf(1921)
# ------------------------------------------------------------------------------------------------
# Function calling
# ------------------------------------------------------------------------------------------------
# Vars setting
#1
mySetLong(vFunction, 1)
#2
string_value_to_write = 'A'
mySetString(vText, string_value_to_write)
#3
mySetLong(vTextLen, len(string_value_to_write))
#4
mySetLong(vResult, 1)
#Call the function
calldll.call_foreign_function (
address,
'llll',
'l',
(vFunction.address(), vText.address(), vTextLen.address(), vResult.address())
)
myPrintLong(vResult)
myPrintString(vText)
# ------------------------------------------------------------------------------------------------
# Dll unloading
# ------------------------------------------------------------------------------------------------
#Unload the dll
calldll.free_library (handle)
|
Some days ago I had to call a Windows dll (who needs int and char pointers) with calldll, and I failed. Then I discovered ctypes (http://starship.python.net/crew/theller/ctypes.html) and it was trivial. However I'd like to use also calldll (http://www.nightmare.com/software.html)... I won, and the code I posted 'll show you the two solutions. I posted the calldll solution because there is so few documentation, and I think my code can help someone ;-) The ctypes code is posted only to show you this beautiful library I hope become famous.