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 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405
|
#! /usr/bin/env python
##
## gen-teem.py: automatically-generated ctypes python wrappers for Teem
## Copyright (C) 2013, 2012, 2011 University of Chicago
## (originally created by Sam Quinan - samquinan@cs.uchicago.edu)
##
## Permission is hereby granted, free of charge, to any person obtaining
## a copy of this software and associated documentation files (the
## "Software"), to deal in the Software without restriction, including
## without limitation the rights to use, copy, modify, merge, publish,
## distribute, sublicense, and/or sell copies of the Software, and to
## permit persons to whom the Software is furnished to do so, subject to
## the following conditions:
##
## The above copyright notice and this permission notice shall be
## included in all copies or substantial portions of the Software.
##
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
## EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
## MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
## NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
## LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
## OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
## WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
##
##
## for posterity; this records the contents of the sourceme-ctypeslib.txt
## file that this script automates ...
oldtodo="""
echo === These are commands that GLK used to create teem.py, in tcsh
echo === Obviously, anyone is welcome to make this into a proper python script
echo === or otherwise make it more robust and portable, especially the stuff
echo === that removes the install path specifics from teem.py
echo ===
echo === You will need a recent gccxml to make this work.
svn co http://svn.python.org/projects/ctypes/branches/ctypeslib-gccxml-0.9
setenv CTYPES `pwd`/ctypeslib-gccxml-0.9
setenv PYTHONPATH ${CTYPES}:`pwd`
echo === A patch is still needed, hopefully this can be fixed
patch -p0 -i ctypes-codegen.patch
echo === TEEM has to be set to wherever CMake put its make install
setenv TEEM /Users/gk/teem-install
echo === all.h just includes all the other public top-level .h in Teem
rm -rf teemincl
mkdir teemincl
cp -r ${TEEM}/include/teem teemincl
cd teemincl
ls -1 teem/*.h | awk '{print "#include <"$1">"}' > all.h
cd ..
echo === teem.xml represents the Teem API
python ${CTYPES}/scripts/h2xml.py `pwd`/teemincl/all.h -I teemincl -o teem.xml
echo === DYLD_LIBRARY_PATH is obviously Mac specific, please fix
setenv DYLD_LIBRARY_PATH ${TEEM}/lib
python ${CTYPES}/scripts/xml2py.py teem.xml -llibteem.dylib -o pre-teem.py -m stdio \
-r "(air|hest|biff|nrrd|ell|unrrdu|alan|moss|tijk|gage|dye|bane|limn|echo|hoover|seek|ten|elf|pull|coil|push|mite|meet).*"
rm -rf teemincl
echo === At this point GLK does emacs stuff to make pre-teem.py into what is
echo === the currently svn committed teem.py
echo === Obviously, this really needs to be automated...
"""
# and now it has been automated!
import os, sys, shutil, platform, re, string
if len(sys.argv) != 3:
sys.exit("usage: gen-teem.py <ctypeslib-gccxml source dir> <teem install dir>")
## (TEEM_LIB_LIST)
libs_list = ["air", "hest", "biff", "nrrd", "ell", "unrrdu", "alan", "moss", "tijk", "gage", "dye", "bane", "limn", "echo", "hoover", "seek", "ten", "elf", "pull", "coil", "push", "mite", "meet"]
#
# validate os
#
if os.name != "posix":
sys.exit("program only supports posix compilant systems at this time")
#
# validate gccxml install
#
tmp = os.path.join(os.getcwd(), "tmp")
os.system("gccxml --version &> tmp")
file = open(tmp, "r")
file.seek(0)
first_line = file.readline()
file.close()
if not first_line.startswith("GCC-XML version"):
os.remove(tmp)
sys.exit("error: gccxml of version >= 0.9.0 is required for this script")
if not ((int(first_line[16]) > 0) or ((int(first_line[18]) == 9) and (int(first_line[20]) >= 0))):
os.remove(tmp)
sys.exit("error: gccxml of version >= 0.9.0 is required for this script")
os.remove(tmp)
#
# validate ctypeslib-gccxml source dir path
#
if not os.path.isdir(sys.argv[1]):
sys.exit("%s does not point to a directory" % sys.argv[1])
CTYPES = os.path.abspath(sys.argv[1])
#
# NOTE, however, that this really assumes a PATCHED ctypeslib-gccxml,
# via a procedure like:
# svn co http://svn.python.org/projects/ctypes/branches/ctypeslib-gccxml-0.9
# patch -p0 -i ctypes-codegen.patch
#
# validate teem install dir path
#
if not os.path.isdir(sys.argv[2]):
sys.exit("%s does not point to a directory" % sys.argv[2])
TEEM = os.path.abspath(sys.argv[2])
#
# copy files from install dir
#
TMP_DIR = "gen-teem-tmp"
teem_include = os.path.join(TEEM, "include")
if not os.path.isdir(teem_include):
sys.exit("%s is not the teem install directory; %s is not a valid path" % (teem, teem-install))
if os.path.isdir(TMP_DIR):
shutil.rmtree(TMP_DIR)
shutil.copytree(teem_include, TMP_DIR)
#
# generate all.h
#
all_h = os.path.join(TMP_DIR, "all.h")
f_open = open (all_h, "w")
defines = []
Files = os.listdir(os.path.join(TMP_DIR, "teem"))
for file in Files:
if file.endswith(".h"):
f_open.write("#include <teem/%s> %s" % (file, os.linesep))
#
# get #define statements from file
#
lines = open (os.path.join(TMP_DIR, "teem", file), "r").readlines()
expr1 = re.compile("^#define")
expr2 = re.compile("\\\\")
expr3 = re.compile("HAS_BEEN_INCLUDED")
expr4 = re.compile("##")
expr5 = re.compile("^#define [^ ]*\(")
expr6 = re.compile("NRRD_TYPE_BIGGEST")
# this strips out NRRD_LLONG_MAX, NRRD_LLONG_MIN, and NRRD_ULLONG_MAX,
# which depend on macros AIR_LLONG and AIR_LLONG. For some reason
# this causes a problem now (Thu Jun 14 11:49:14 CDT 2012) even though
# they haven't before, though these constants and macros are not new
expr7 = re.compile("LLONG")
for line in lines:
if (expr1.search(line) and not expr2.search(line)
and not expr3.search(line) and not expr4.search(line)
and not expr5.search(line) and not expr6.search(line)
and not expr7.search(line)):
firstword, restwords = string.replace(string.replace(line[8:], "/*", "#" ), "*/", "").split(None,1)
defines.append("%s = %s" % (firstword, restwords))
f_open.close()
#
# generate teem.xml
#
# note: these calls are unix only because windows support for command line
# append to python path (where the scopeis only that one call) is too
# difficult at this time -- better support may be added to later versions
# of python, so that something to watch for / modify in the future
pypath_append = "PYTHONPATH=%s:%s" % (CTYPES, os.getcwd())
teem_xml = os.path.join(os.getcwd(), "teem.xml")
os.system("%s python %s %s -I %s -o %s" % (pypath_append, os.path.join(CTYPES, "scripts", "h2xml.py"), os.path.abspath(all_h), TMP_DIR, teem_xml))
#
# generate pre-teem.py
#
pre_teem_py = os.path.join(os.getcwd(), "pre-teem.py")
teem_libs = '|'.join(libs_list)
system_type = platform.system()
dll_path = ""
ext = ""
substr = ""
if system_type == "Darwin":
dll_path = "DYLD_LIBRARY_PATH=%s" % os.path.join(TEEM, "lib")
ext = "dylib"
substr = "_libraries['%s']" % os.path.join(TEEM, "lib", "libteem.dylib")
else:
dll_path = "LD_LIBRARY_PATH=%s" % os.path.join(TEEM, "lib")
ext = "so"
substr = "_libraries['libteem.so']"
os.system("%s %s python %s %s -l libteem.%s -o %s -m stdio -r \"(%s).*\"" % (dll_path, pypath_append, os.path.join(CTYPES, "scripts", "xml2py.py"), teem_xml, ext, pre_teem_py, teem_libs))
#
# generate teem.py
#
libs_destuctable = list(libs_list)
contents = open(pre_teem_py, "r").readlines()[8:]
mod_contents = []
for line in contents:
l = line.replace(substr, "libteem")
if not (("__darwin_size_t = c_ulong" in l) or ("size_t = __darwin_size_t" in l)):
l2 = l.replace("\'__darwin_size_t\',", "") #designed to remove defs from long list at end
l3 = l2.replace("\'size_t\',", "") #designed to remove defs from long list at end
l = l3
if not re.compile("_size_t").search(l3):
if not re.match("#", l3): # i.e. do not make changes in commented lines
l = l3.replace("size_t", "c_size_t")
mod_contents.append(l)
if "Present" in l:
for lib in libs_destuctable:
lib_str = lib+"Present"
if lib_str in l:
libs_destuctable.remove(lib)
break
# in experimental libs not included, cleanup and fail
if libs_destuctable: # empty sequence implicity false
shutil.rmtree(TMP_DIR)
os.remove(teem_xml)
#os.remove(pre_teem_py)
sys.exit("ERROR: experimental libs: %s not turned on - please rebuild teem with BUILD_EXPERIMENTAL_LIBS turned on, then re-run gen-teem.py" % ','.join(libs_destuctable))
header = [
"##",
"## teem.py: automatically-generated ctypes python wrappers for Teem",
"## Copyright (C) 2013, 2012, 2011, 2010, 2009 University of Chicago",
"##",
"## Permission is hereby granted, free of charge, to any person obtaining",
"## a copy of this software and associated documentation files (the",
"## \"Software\"), to deal in the Software without restriction, including",
"## without limitation the rights to use, copy, modify, merge, publish,",
"## distribute, sublicense, and/or sell copies of the Software, and to",
"## permit persons to whom the Software is furnished to do so, subject to",
"## the following conditions:",
"##",
"## The above copyright notice and this permission notice shall be",
"## included in all copies or substantial portions of the Software.",
"##",
"## THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,",
"## EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF",
"## MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND",
"## NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE",
"## LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION",
"## OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION",
"## WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.",
"##",
"##############################################################",
"##############################################################",
"#### NOTE: This teem.py file is automatically produced by",
"#### teem/python/ctypes/gen-teem.py. Necessary changes to ",
"#### teem.py should be made in gen-teem.py, not here.",
"##############################################################",
"##############################################################",
"",
"from ctypes import *",
"import ctypes.util",
"import sys, os",
"",
"def load_library(libname, loader_path=\"\"):",
" ext = os.path.splitext(libname)[1]",
" if not ext:",
" # Try to load library with platform-specific name",
" if sys.platform == 'win32':",
" libname_ext = '%s.dll' % libname",
" elif sys.platform == 'darwin':",
" libname_ext = '%s.dylib' % libname",
" elif sys.platform == 'linux2':",
" libname_ext = '%s.so' % libname",
" else:"
" libname_ext = libname",
"",
" if (loader_path != \"\"):",
" loader_path = os.path.abspath(loader_path)",
" if not os.path.isdir(loader_path):",
" libdir = os.path.dirname(loader_path)",
" else:",
" libdir = loader_path",
" else:",
" libdir = loader_path",
"",
" try:",
" libpath = os.path.join(libdir, libname_ext)",
" return CDLL(libpath)",
" except OSError, e:",
" raise e"
"",
"try:",
" libteem = load_library('libteem')",
"except OSError:",
" print \"**\"",
" print \"** teem.py couldn't find and load the \\\"libteem\\\" shared library.\"",
" print \"**\"",
" print \"** try setting optional loader_path argument in the load_library() call above to '<teem-install-dir>/lib/'\"",
" print \"**\"",
" raise ImportError",
"",
"# =============================================================",
"# Utility types and classes to help teem.py be platform-independent.",
"",
"STRING = c_char_p",
"",
"class FILE(Structure):",
" pass",
"",
"# oddly, size_t is in ctypes, but not ptrdiff_t",
"# which is probably a bug",
"if sizeof(c_void_p) == 4:",
" ptrdiff_t = c_int32",
"elif sizeof(c_void_p) == 8:",
" ptrdiff_t = c_int64",
"",
"# =============================================================",
"# What follows are all the functions, struct definitions, globals, ",
"# enum values, and typedefs in Teem. This is generated by ctypeslib:",
"# http://svn.python.org/projects/ctypes/branches/ctypeslib-gccxml-0.9",
"# followed by further post-processing and filtering.",
"# See end of this file for definitions of stderr, stdin, stdout",
]
footer = [
"# =============================================================",
"# Make sure this shared library will work on this machine.",
"if not nrrdSanity():",
" errstr = biffGetDone(NRRD)",
" print \"**\"",
" print \"** Sorry, there is a problem (described below) with the \"",
" print \"** Teem shared library that prevents its use. This will \"",
" print \"** have to be fixed by recompiling the Teem library for \"",
" print \"** this platform. \"",
" print \"**\"",
" print \"** %s\" % errstr",
" raise ImportError",
"",
"# =============================================================",
"# Its nice to have these FILE*s around for utility use, but they ",
"# aren't available in a platform-independent way in ctypes. These ",
"# air functions were created for this purpose.",
"stderr = airStderr()",
"stdout = airStdout()",
"stdin = airStdin()",
]
teem_py = os.path.join(os.getcwd(), "teem.py")
if os.path.exists(teem_py):
os.remove(teem_py)
out = open(teem_py, "w")
for line in header:
out.write(line)
out.write(os.linesep)
out.writelines(mod_contents)
out.write(os.linesep)
out.write("# =============================================================\n")
out.write("# What follows are the all #define's in Teem, excluding macros,\n")
out.write("# and #defines that depend on compile-time tests done by the\n")
out.write("# C pre-processor.\n")
out.write("# This is created by something akin to grep'ing through the\n")
out.write("# public header files, with some extra filters.\n")
out.write(os.linesep)
out.writelines(defines)
out.write(os.linesep)
for line in footer:
out.write(line)
out.write(os.linesep)
out.close()
#
# cleanup
#
shutil.rmtree(TMP_DIR)
os.remove(teem_xml)
os.remove(pre_teem_py)
|