pycxx-6.2.5/000755 000771 000000 00000000000 12204160454 013147 5ustar00barrywheel000000 000000 pycxx-6.2.5/build-all.cmd000644 000771 000000 00000001227 12204154670 015506 0ustar00barrywheel000000 000000 setlocal call setup-msvc90 c:\python27.win32\python setup_makefile.py win32 win32.mak nmake -f win32.mak clean all 2>&1 | c:\unxutils\tee tmp-python27-build.log nmake -f win32.mak test 2>&1 | c:\unxutils\tee tmp-python27-test.log c:\python32.win32\python setup_makefile.py win32 win32.mak nmake -f win32.mak clean all 2>&1 | c:\unxutils\tee tmp-python32-build.log nmake -f win32.mak test 2>&1 | c:\unxutils\tee tmp-python32-test.log c:\python33.win32\python setup_makefile.py win32 win32.mak nmake -f win32.mak clean all 2>&1 | c:\unxutils\tee tmp-python33-build.log nmake -f win32.mak test 2>&1 | c:\unxutils\tee tmp-python33-test.log endlocal pycxx-6.2.5/build-all.sh000755 000771 000000 00000000620 12160124242 015345 0ustar00barrywheel000000 000000 #!/bin/bash set -e OS=${1:-macosx} for PYTHON in \ python2.4 \ python2.5 \ python2.6 \ python2.7 \ python3.2 \ python3.3 \ ; do if which $PYTHON >/dev/null then ${PYTHON} setup_makefile.py ${OS} tmp-$PYTHON.mak make -f tmp-$PYTHON.mak clean 2>&1 | tee tmp-$PYTHON.log make -f tmp-$PYTHON.mak test 2>&1 | tee -a tmp-$PYTHON.log fi done pycxx-6.2.5/COPYRIGHT000644 000771 000000 00000006226 10547732521 014460 0ustar00barrywheel000000 000000 Copyright (c) 1998 - 2007 The Regents of the University of California Produced at the Lawrence Livermore National Laboratory Written by Geoff Furnish, Paul F. Dubois, Barry A. Scott UCRL-CODE-227018 All rights reserved. This file is part of PyCXX. For details, see http://cxx.sourceforge.net. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the disclaimer below. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the disclaimer (as noted below) in the documentation and/or materials provided with the distribution. - Neither the name of the UC/LLNL nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Additional BSD Notice 1. This notice is required to be provided under our contract with the U.S. Department of Energy (DOE). This work was produced at the University of California, Lawrence Livermore National Laboratory under Contract No. W-7405-ENG-48 with the DOE. 2. Neither the United States Government nor the University of California nor any of their employees, makes any warranty, express or implied, or assumes any liability or responsibility for the accuracy, completeness, or usefulness of any information, apparatus, product, or process disclosed, or represents that its use would not infringe privately-owned rights. 3. Also, reference herein to any specific commercial products, process, or services by trade name, trademark, manufacturer or otherwise does not necessarily constitute or imply its endorsement, recommendation, or favoring by the United States Government or the University of California. The views and opinions of authors expressed herein do not necessarily state or reflect those of the United States Government or the University of California, and shall not be used for advertising or product endorsement purposes. pycxx-6.2.5/CXX/000755 000771 000000 00000000000 12204160454 013611 5ustar00barrywheel000000 000000 pycxx-6.2.5/Demo/000755 000771 000000 00000000000 12204160454 014033 5ustar00barrywheel000000 000000 pycxx-6.2.5/Doc/000755 000771 000000 00000000000 12204160454 013654 5ustar00barrywheel000000 000000 pycxx-6.2.5/how_to_release_pycxx.txt000644 000771 000000 00000001722 11724522650 020152 0ustar00barrywheel000000 000000 How to release PyCXX -------------------- 0. Update CXX/Version.hxx with the releases version number Update README.html, PyCXX-Release-Notes.txt and SourceForge/index.html with change log info 1. Tag the source using tag_pycxx.py (depends on pysvn). 2. Create the source kit using make_src_kit.py 3. Add new File release on sourceforge. 1. http://sourceforge.net/projects/cxx/ 3. Select File 4. Create New Folder 5. Name the Folder PyCXX V.. e.g. PyCXX V6.1.1 7. Upload the source kit and its PyCXX-Release-Notes-readme.txt (as README.txt) 9. Click on the source kit (i) icon and choose Select All platforms 4. Add news about release 1. Click Develop 2. From Develop Menu choose News 3. Add news with release note info - may be need to make it a bigger advert? 4. Click Submit to slashdot and Submit 5. Email CXX mailing lists 6. Update docs on the PyCXX homepage 1. cd SourceForge 2. ./deploy.sh pycxx-6.2.5/Lib/000755 000771 000000 00000000000 12204160454 013655 5ustar00barrywheel000000 000000 pycxx-6.2.5/make_src_kit.py000644 000771 000000 00000002150 11132160151 016143 0ustar00barrywheel000000 000000 import sys import os import shutil def main( argv ): f = open( 'CXX/Version.hxx' ) major = None minor = None patch = None for line in f: words = line.split() if words[0:2] == ['#define', 'PYCXX_VERSION_MAJOR']: major = words[2] if words[0:2] == ['#define', 'PYCXX_VERSION_MINOR']: minor = words[2] if words[0:2] == ['#define', 'PYCXX_VERSION_PATCH']: patch = words[2] print( 'version: %s, %s, %s' % (major, minor, patch) ) tmp_dir = os.environ.get('TMP','/tmp') kit_name = 'pycxx-%s.%s.%s' % (major, minor, patch) kit_dir = os.path.join( tmp_dir, kit_name ) if os.path.exists( kit_dir ): print( 'Info: Removing tree at %s' % kit_dir ) shutil.rmtree( kit_dir ) os.mkdir( kit_dir ) print( 'Info: svn export %s' % kit_dir ) os.system( 'svn export --force . %s' % kit_dir ) print( 'Info: Creating %s.tar.gz' % kit_dir ) os.chdir( tmp_dir ) os.system( 'tar czf %s.tar.gz %s' % (kit_dir, kit_name) ) return 0 if __name__ == '__main__': sys.exit( main( sys.argv ) ) pycxx-6.2.5/obj/000755 000771 000000 00000000000 12204160454 013721 5ustar00barrywheel000000 000000 pycxx-6.2.5/README.html000644 000771 000000 00000007110 12136020574 014773 0ustar00barrywheel000000 000000 PyCXX README

PyCXX -- README

Installation using distutils

Windows Installation and Demo

  1. Fetch http://prdownloads.sourceforge.net/cxx/pycxx-6.2.4.tar.gz
  2. Expand the archive into a directory of your choosing C:\ for example. Note: WinZip can expand .tar.gz files.
  3. Install the PyCXX files:
    1. C:> cd \pycxx-6.2.4
    2. C:\pycxx-6.2.4> python setup.py install
  4. Build and run the demo extensions:
    1. C:> cd \pycxx-6.2.4
    2. C:\pycxx-6.2.4> python setup_makefile.py win32 win32.mak 
    3. C:\pycxx-6.2.4> nmake -f win32.mak clean test

Unix Installation and Demo

Note: distutils is not available for Python 1.5.2

  1. Fetch http://prdownloads.sourceforge.net/cxx/pycxx-6.2.4.tar.gz
  2. Login as root. root access is typically needed on Unix systems to install the PyCXX files into the Python directories.
  3. Expand the archive into a directory of your choosing ~\ for example.
  4. Install the PyCXX files:
    1. # cd ~\pycxx-6.2.4
    2. # python setup.py install
  5. Build and run the demo extensions:
    1. # cd ~\pycxx-6.2.4\Demo\Python2
    2. # python setup_makefile.py linux linux.mak
    3. # make -f linux.mak clean test

Revision History

Version 6.2.4 (6-Feb-2011)

Fix memory leak in string encode and decode functions

Fix indirect python loading on windows - Bool_type was missing

Version 6.2.2 (26-Dec-2010)

Fix problem compiling against Python 3.1.3

Version 6.2.1 (3-May-2010)

Fix problems with new style classes

Replace all example makefile and project files with setup_makefile.py script.

Add APIs to make calling python functions easier. See TupleN(), callOnSelf(), self()

Version 6.1.1 (26-Sep-2009)

Supports Python 3 starting at Python 3.1 and Python 2

Code clean up to fix compiler warnings reported by gcc 4.2.1 on Mac OS X when building for Python 3.

Version 6.1.0 (19-Jul-2009)

Support Python 3 and Python 2

pycxx-6.2.5/RegressionTests/000755 000771 000000 00000000000 12204160454 016312 5ustar00barrywheel000000 000000 pycxx-6.2.5/run_tests.cmd000644 000771 000000 00000000473 11146621572 015675 0ustar00barrywheel000000 000000 setlocal set PY_MAJ=2 if not "%1" == "" set PY_MAJ=%1 set PY_MIN=5 if not "%2" == "" set PY_MIN=%2 set PYTHONPATH=pyds%PY_MAJ%%PY_MIN% c:\python%PY_MAJ%%PY_MIN%\python Demo\test_example.py if exist pyds%PY_MAJ%%PY_MIN%\pycxx_iter.pyd c:\python%PY_MAJ%%PY_MIN%\python Demo\test_pycxx_iter.py endlocal pycxx-6.2.5/setup.py000755 000771 000000 00000002171 12160122356 014665 0ustar00barrywheel000000 000000 import os, sys from glob import glob from distutils.command.install import install from distutils.core import setup headers = (glob( os.path.join( "CXX","*.hxx" ) ) +glob( os.path.join( "CXX","*.h" ) )) sources = (glob( os.path.join( "Src", "*.cxx" ) ) +glob( os.path.join( "Src", "*.c" ) )) class my_install (install): def finalize_options (self): if not self.install_data or (len(self.install_data) < 8) : self.install_data = "$base/share/python$py_version_short" install.finalize_options (self) def run (self): self.distribution.data_files = [("CXX", sources)] self.distribution.headers = headers install.run (self) setup (name = "CXX", version = "6.2.4", maintainer = "Barry Scott", maintainer_email = "barry-scott@users.sourceforge.net", description = "Facility for extending Python with C++", url = "http://cxx.sourceforge.net", cmdclass = {'install': my_install}, packages = ['CXX'], package_dir = {'CXX': 'Lib'} ) pycxx-6.2.5/setup_makefile.py000644 000771 000000 00000047260 11655276224 016543 0ustar00barrywheel000000 000000 # # Copyright (c) 2010-2011 Barry A. Scott # import os import sys import distutils import distutils.sysconfig import distutils.util _debug = False def debug( msg ): if _debug: sys.stderr.write( 'Debug: %s\n' % (msg,) ) #-------------------------------------------------------------------------------- class Setup: def __init__( self, argv ): args = argv[1:] if len(args) < 2: raise ValueError( 'Usage: setup.py win32|macosx|linux> ' ) self.opt_debug = False self.platform = args[0] del args[0] self.__makefile = open( args[0], 'wt' ) del args[0] while len(args) > 0: if args[0] == '--debug': self.opt_debug = True del args[0] else: raise ValueError( 'Unknown arg %r' % (args[0],) ) self.setupCompile() def makePrint( self, line ): self.__makefile.write( line ) self.__makefile.write( '\n' ) def setupCompile( self ): if self.platform == 'win32': self.c_utils = Win32CompilerMSVC90( self ) self.c_python_extension = Win32CompilerMSVC90( self ) elif self.platform == 'macosx': self.c_utils = MacOsxCompilerGCC( self ) self.c_python_extension = MacOsxCompilerGCC( self ) elif self.platform == 'linux': self.c_utils = LinuxCompilerGCC( self ) self.c_python_extension = LinuxCompilerGCC( self ) else: raise ValueError( 'Unknown platform %r' % (self.platform,) ) self.c_python_extension.setupPythonExtension() self.pycxx_obj_file = [ Source( self.c_python_extension, 'Src/cxxsupport.cxx' ), Source( self.c_python_extension, 'Src/cxx_extensions.cxx' ), Source( self.c_python_extension, 'Src/cxxextensions.c' ), Source( self.c_python_extension, 'Src/IndirectPythonInterface.cxx' ), ] self.simple_obj_files = [ Source( self.c_python_extension, '%(DEMO_DIR)s/simple.cxx' ), ] + self.pycxx_obj_file self.example_obj_files = [ Source( self.c_python_extension, '%(DEMO_DIR)s/example.cxx' ), Source( self.c_python_extension, '%(DEMO_DIR)s/range.cxx' ), Source( self.c_python_extension, '%(DEMO_DIR)s/rangetest.cxx' ), ] + self.pycxx_obj_file self.pycxx_iter_obj_files = [ Source( self.c_python_extension, '%(DEMO_DIR)s/pycxx_iter.cxx' ), ] + self.pycxx_obj_file exe_simple = PythonExtension( self.c_python_extension, 'simple', self.simple_obj_files ) exe_example = PythonExtension( self.c_python_extension, 'example', self.example_obj_files ) exe_pycxx_iter = PythonExtension( self.c_python_extension, 'pycxx_iter', self.pycxx_iter_obj_files ) self.all_exe = [ exe_simple, exe_example, exe_pycxx_iter, ] self.all_test = [ TestPythonExtension( self.c_python_extension, '%(DEMO_DIR)s/test_simple.py', exe_simple ), TestPythonExtension( self.c_python_extension, '%(DEMO_DIR)s/test_example.py', exe_example ), TestPythonExtension( self.c_python_extension, '%(DEMO_DIR)s/test_pycxx_iter.py', exe_pycxx_iter ), ] def generateMakefile( self ): try: self.c_python_extension.generateMakefileHeader() self.makePrint( 'all: %s' % (' '.join( [exe.getTargetFilename() for exe in self.all_exe] )) ) self.makePrint( '' ) for exe in self.all_exe: exe.generateMakefile() for test in self.all_test: test.generateMakefile() self.__makefile.close() return 0 except ValueError: e = sys.exc_info()[1] sys.stderr.write( 'Error: %s\n' % (e,) ) return 1 #-------------------------------------------------------------------------------- class Compiler: def __init__( self, setup ): debug( 'Compiler.__init__()' ) self.setup = setup self.__variables = {} self._addVar( 'DEBUG', 'NDEBUG') def platformFilename( self, filename ): return filename def makePrint( self, line ): self.setup.makePrint( line ) def generateMakefileHeader( self ): raise NotImplementedError( 'generateMakefileHeader' ) def _addFromEnv( self, name ): debug( 'Compiler._addFromEnv( %r )' % (name,) ) self._addVar( name, os.environ[ name ] ) def _addVar( self, name, value ): debug( 'Compiler._addVar( %r, %r )' % (name, value) ) try: if '%' in value: value = value % self.__variables self.__variables[ name ] = value except TypeError: raise ValueError( 'Cannot translate name %r value %r' % (name, value) ) except KeyError: e = sys.exc_info()[1] raise ValueError( 'Cannot translate name %r value %r - %s' % (name, value, e) ) def expand( self, s ): try: return s % self.__variables except (TypeError, KeyError): e = sys.exc_info()[1] print( 'Error: %s' % (e,) ) print( 'String: %s' % (s,) ) print( 'Vairables: %r' % (self.__variables,) ) raise ValueError( 'Cannot translate string (%s)' % (e,) ) class Win32CompilerMSVC90(Compiler): def __init__( self, setup ): Compiler.__init__( self, setup ) self._addVar( 'PYTHONDIR', sys.exec_prefix ) self._addVar( 'PYTHON_LIBNAME', 'python%d%d' % (sys.version_info[0], sys.version_info[1]) ) self._addVar( 'PYTHON_INCLUDE', r'%(PYTHONDIR)s\include' ) self._addVar( 'PYTHON_LIB', r'%(PYTHONDIR)s\libs' ) self._addVar( 'PYTHON', sys.executable ) def platformFilename( self, filename ): return filename.replace( '/', '\\' ) def getPythonExtensionFileExt( self ): return '.pyd' def getProgramExt( self ): return '.exe' def generateMakefileHeader( self ): self.makePrint( '#' ) self.makePrint( '# Bemacs Makefile generated by setup.py' ) self.makePrint( '#' ) self.makePrint( 'CCC=cl /nologo' ) self.makePrint( 'CC=cl /nologo' ) self.makePrint( '' ) self.makePrint( 'LDSHARED=$(CCC) /LD /Zi /MT /EHsc' ) self.makePrint( 'LDEXE=$(CCC) /Zi /MT /EHsc' ) self.makePrint( '' ) def ruleLinkProgram( self, target ): pyd_filename = target.getTargetFilename() pdf_filename = target.getTargetFilename( '.pdf' ) all_objects = [source.getTargetFilename() for source in target.all_sources] rules = [''] rules.append( '' ) rules.append( '%s : %s' % (pyd_filename, ' '.join( all_objects )) ) rules.append( '\t@echo Link %s' % (pyd_filename,) ) rules.append( '\t$(LDEXE) %%(CCCFLAGS)s /Fe%s /Fd%s %s Advapi32.lib' % (pyd_filename, pdf_filename, ' '.join( all_objects )) ) self.makePrint( self.expand( '\n'.join( rules ) ) ) def ruleLinkShared( self, target ): pyd_filename = target.getTargetFilename() pdf_filename = target.getTargetFilename( '.pdf' ) all_objects = [source.getTargetFilename() for source in target.all_sources] rules = [''] rules.append( '' ) rules.append( '%s : %s' % (pyd_filename, ' '.join( all_objects )) ) rules.append( '\t@echo Link %s' % (pyd_filename,) ) rules.append( '\t$(LDSHARED) %%(CCCFLAGS)s /Fe%s /Fd%s %s %%(PYTHON_LIB)s\%%(PYTHON_LIBNAME)s.lib' % (pyd_filename, pdf_filename, ' '.join( all_objects )) ) self.makePrint( self.expand( '\n'.join( rules ) ) ) def ruleCxx( self, target ): obj_filename = target.getTargetFilename() rules = [] rules.append( '%s: %s %s' % (obj_filename, target.src_filename, ' '.join( target.all_dependencies )) ) rules.append( '\t@echo Compile: %s into %s' % (target.src_filename, target.getTargetFilename()) ) rules.append( '\t$(CCC) /c %%(CCCFLAGS)s /Fo%s /Fd%s %s' % (obj_filename, target.dependent.getTargetFilename( '.pdb' ), target.src_filename) ) self.makePrint( self.expand( '\n'.join( rules ) ) ) def ruleC( self, target ): # can reuse the C++ rule self.ruleCxx( target ) def ruleClean( self, filename ): rules = [] rules.append( 'clean::' ) rules.append( '\tif exist %s del %s' % (filename, filename) ) rules.append( '' ) self.makePrint( self.expand( '\n'.join( rules ) ) ) def setupPythonExtension( self ): self._addVar( 'PYTHON', sys.executable ) self._addVar( 'OBJ_DIR', 'obj' ) self._addVar( 'PYTHON_VERSION', '%d.%d' % (sys.version_info[0], sys.version_info[1]) ) self._addVar( 'DEMO_DIR', 'Demo\Python%d' % (sys.version_info[0],) ) self._addVar( 'CCCFLAGS', r'/Zi /MT /EHsc ' r'-I. -ISrc -I%(PYTHON_INCLUDE)s ' r'-D_CRT_NONSTDC_NO_DEPRECATE ' r'-U_DEBUG ' r'-D%(DEBUG)s' ) def ruleTest( self, python_test ): rules = [] rules.append( 'test:: %s %s' % (python_test.getTargetFilename(), python_test.python_extension.getTargetFilename()) ) rules.append( '\tset PYTHONPATH=obj' ) rules.append( '\t%%(PYTHON)s -W default %s' % (python_test.getTargetFilename(),) ) rules.append( '' ) self.makePrint( self.expand( '\n'.join( rules ) ) ) class CompilerGCC(Compiler): def __init__( self, setup ): Compiler.__init__( self, setup ) if self.setup.platform == 'macosx': if sys.version_info[0] == 2: maxsize = sys.maxint else: maxsize = sys.maxsize if maxsize == (2**31-1): arch = 'i386' else: arch = 'x86_64' self._addVar( 'CCC', 'g++ -arch %s' % (arch,) ) self._addVar( 'CC', 'gcc -arch %s' % (arch,) ) else: self._addVar( 'CCC', 'g++' ) self._addVar( 'CC', 'gcc' ) def getPythonExtensionFileExt( self ): return '.so' def getProgramExt( self ): return '' def generateMakefileHeader( self ): self.makePrint( '#' ) self.makePrint( '# Bemacs Makefile generated by setup.py' ) self.makePrint( '#' ) self.makePrint( '' ) def ruleLinkProgram( self, target ): target_filename = target.getTargetFilename() all_objects = [source.getTargetFilename() for source in target.all_sources] rules = [] rules.append( '%s : %s' % (target_filename, ' '.join( all_objects )) ) rules.append( '\t@echo Link %s' % (target_filename,) ) rules.append( '\t%%(LDEXE)s -o %s %%(CCCFLAGS)s %s' % (target_filename, ' '.join( all_objects )) ) self.makePrint( self.expand( '\n'.join( rules ) ) ) def ruleLinkShared( self, target ): target_filename = target.getTargetFilename() all_objects = [source.getTargetFilename() for source in target.all_sources] rules = [] rules.append( '%s : %s' % (target_filename, ' '.join( all_objects )) ) rules.append( '\t@echo Link %s' % (target_filename,) ) rules.append( '\t%%(LDSHARED)s -o %s %%(CCCFLAGS)s %s' % (target_filename, ' '.join( all_objects )) ) self.makePrint( self.expand( '\n'.join( rules ) ) ) def ruleCxx( self, target ): obj_filename = target.getTargetFilename() rules = [] rules.append( '%s: %s %s' % (obj_filename, target.src_filename, ' '.join( target.all_dependencies )) ) rules.append( '\t@echo Compile: %s into %s' % (target.src_filename, obj_filename) ) rules.append( '\t%%(CCC)s -c %%(CCCFLAGS)s -o%s %s' % (obj_filename, target.src_filename) ) self.makePrint( self.expand( '\n'.join( rules ) ) ) def ruleC( self, target ): obj_filename = target.getTargetFilename() rules = [] rules.append( '%s: %s %s' % (obj_filename, target.src_filename, ' '.join( target.all_dependencies )) ) rules.append( '\t@echo Compile: %s into %s' % (target.src_filename, target) ) rules.append( '\t%%(CC)s -c %%(CCCFLAGS)s -o%s %s' % (obj_filename, target.src_filename) ) self.makePrint( self.expand( '\n'.join( rules ) ) ) def ruleClean( self, filename ): rules = [] rules.append( 'clean::' ) rules.append( '\trm -f %s' % (filename,) ) rules.append( '' ) self.makePrint( self.expand( '\n'.join( rules ) ) ) def ruleTest( self, python_test ): rules = [] rules.append( 'test:: %s %s' % (python_test.getTargetFilename(), python_test.python_extension.getTargetFilename()) ) rules.append( '\tPYTHONPATH=obj %%(PYTHON)s -W default %s' % (python_test.getTargetFilename(),) ) rules.append( '' ) self.makePrint( self.expand( '\n'.join( rules ) ) ) class MacOsxCompilerGCC(CompilerGCC): def __init__( self, setup ): CompilerGCC.__init__( self, setup ) def setupPythonExtension( self ): self._addVar( 'PYTHON', sys.executable ) self._addVar( 'OBJ_DIR', 'obj' ) self._addVar( 'PYTHON_VERSION', '%d.%d' % (sys.version_info[0], sys.version_info[1]) ) self._addVar( 'PYTHONDIR', sys.exec_prefix ) self._addVar( 'PYTHON_FRAMEWORK', '%(PYTHONDIR)s/Python' ) self._addVar( 'PYTHON', sys.executable ) self._addVar( 'PYTHON_INCLUDE', '%(PYTHONDIR)s/Headers' ) self._addVar( 'DEMO_DIR', 'Demo/Python%d' % (sys.version_info[0],) ) self._addVar( 'CCCFLAGS', '-g ' '-Wall -fPIC -fexceptions -frtti ' '-I. -ISrc -I%(PYTHON_INCLUDE)s ' '-D%(DEBUG)s' ) self._addVar( 'LDSHARED', '%(CCC)s -bundle -g ' '-framework System ' '%(PYTHON_FRAMEWORK)s ' ) class LinuxCompilerGCC(CompilerGCC): def __init__( self, setup ): CompilerGCC.__init__( self, setup ) def setupPythonExtension( self ): self._addVar( 'PYTHON', sys.executable ) self._addVar( 'OBJ_DIR', 'obj' ) self._addVar( 'DEMO_DIR', 'Demo/Python%d' % (sys.version_info[0],) ) self._addVar( 'PYTHON_VERSION', '%d.%d' % (sys.version_info[0], sys.version_info[1]) ) self._addVar( 'PYTHON_INCLUDE', distutils.sysconfig.get_python_inc() ) self._addVar( 'CCCFLAGS', '-g ' '-Wall -fPIC -fexceptions -frtti ' '-I. -ISrc -I%(PYTHON_INCLUDE)s ' '-D%(DEBUG)s' ) self._addVar( 'LDEXE', '%(CCC)s -g' ) self._addVar( 'LDSHARED', '%(CCC)s -shared -g ' ) #-------------------------------------------------------------------------------- class Target: def __init__( self, compiler, all_sources ): self.compiler = compiler self.__generated = False self.dependent = None self.all_sources = all_sources for source in self.all_sources: source.setDependent( self ) def getTargetFilename( self ): raise NotImplementedError( '%s.getTargetFilename' % self.__class__.__name__ ) def generateMakefile( self ): if self.__generated: return self.__generated = True return self._generateMakefile() def _generateMakefile( self ): raise NotImplementedError( '_generateMakefile' ) def ruleClean( self, ext=None ): if ext is None: target_filename = self.getTargetFilename() else: target_filename = self.getTargetFilename( ext ) self.compiler.ruleClean( target_filename ) def setDependent( self, dependent ): debug( '%r.setDependent( %r )' % (self, dependent,) ) self.dependent = dependent class TestPythonExtension(Target): def __init__( self, compiler, test_source, python_extension ): self.test_source = test_source self.python_extension = python_extension Target.__init__( self, compiler, [] ) def __repr__( self ): return '' % (id(self), self.test_source ) def getTargetFilename( self ): return self.compiler.platformFilename( self.compiler.expand( self.test_source ) ) def _generateMakefile( self ): self.compiler.ruleTest( self ) class PythonExtension(Target): def __init__( self, compiler, output, all_sources ): self.output = output Target.__init__( self, compiler, all_sources ) debug( 'PythonExtension:0x%8.8x.__init__( %r, ... )' % (id(self), output,) ) for source in self.all_sources: source.setDependent( self ) def __repr__( self ): return '' % (id(self), self.output) def getTargetFilename( self, ext=None ): if ext is None: ext = self.compiler.getPythonExtensionFileExt() return self.compiler.platformFilename( self.compiler.expand( '%%(OBJ_DIR)s/%s%s' % (self.output, ext) ) ) def _generateMakefile( self ): debug( 'PythonExtension:0x%8.8x.generateMakefile() for %r' % (id(self), self.output,) ) self.compiler.ruleLinkShared( self ) self.compiler.ruleClean( self.getTargetFilename( '.*' ) ) for source in self.all_sources: source.generateMakefile() class Source(Target): def __init__( self, compiler, src_filename, all_dependencies=None ): self.src_filename = compiler.platformFilename( compiler.expand( src_filename ) ) Target.__init__( self, compiler, [] ) debug( 'Source:0x%8.8x.__init__( %r, %r )' % (id(self), src_filename, all_dependencies) ) self.all_dependencies = all_dependencies if self.all_dependencies is None: self.all_dependencies = [] def __repr__( self ): return '' % (id(self), self.src_filename) def getTargetFilename( self ): #if not os.path.exists( self.src_filename ): # raise ValueError( 'Cannot find source %s' % (self.src_filename,) ) basename = os.path.basename( self.src_filename ) if basename.endswith( '.cpp' ): return self.compiler.platformFilename( self.compiler.expand( r'%%(OBJ_DIR)s/%s.obj' % (basename[:-len('.cpp')],) ) ) if basename.endswith( '.cxx' ): return self.compiler.platformFilename( self.compiler.expand( r'%%(OBJ_DIR)s/%s.obj' % (basename[:-len('.cxx')],) ) ) if basename.endswith( '.c' ): return self.compiler.platformFilename( self.compiler.expand( r'%%(OBJ_DIR)s/%s.obj' % (basename[:-len('.c')],) ) ) raise ValueError( 'unknown source %r' % (self.src_filename,) ) def _generateMakefile( self ): debug( 'Source:0x%8.8x.generateMakefile() for %r' % (id(self), self.src_filename,) ) self.compiler.ruleCxx( self ) self.compiler.ruleClean( self.getTargetFilename() ) #-------------------------------------------------------------------------------- def main( argv ): try: s = Setup( argv ) s.generateMakefile() return 0 except ValueError: e = sys.exc_info()[1] sys.stderr.write( 'Error: %s\n' % (e,) ) return 1 if __name__ == '__main__': sys.exit( main( sys.argv ) ) pycxx-6.2.5/SourceForge/000755 000771 000000 00000000000 12204160454 015372 5ustar00barrywheel000000 000000 pycxx-6.2.5/Src/000755 000771 000000 00000000000 12204160454 013676 5ustar00barrywheel000000 000000 pycxx-6.2.5/tag_pycxx.py000644 000771 000000 00000004112 12204113362 015521 0ustar00barrywheel000000 000000 import pysvn import sys import os def make_tag( from_url, tag_base_url, version ): client = pysvn.Client() client.callback_get_log_message = lambda : (True, 'Tag version '+version) client.callback_get_login = callback_getLogin try: from_files = client.ls( from_url, recurse=False ) print 'Info: Found', from_url except pysvn.ClientError, e: print 'Error: From does not exist',from_url return try: tag_files = client.ls( tag_base_url, recurse=False ) print 'Info: Found', tag_base_url except pysvn.ClientError, e: print 'Error: Tag base does not exist',tag_base_url return cur_versions = [os.path.basename(f['name']) for f in tag_files] if version in cur_versions: print 'Error: Already tagged',version return try: to_url = tag_base_url + '/' + version print 'Info: Copy',repr(from_url), repr(to_url) client.copy( from_url, to_url ) print 'Info: Copy complete' except pysvn.ClientError, e: print 'Error: ', str(e) return def callback_getLogin( realm, username, may_save ): print 'May save:',may_save print 'Realm:',realm if username: print 'Username:',username else: sys.stdout.write( 'Username: ' ) username = sys.stdin.readline().strip() if len(username) == 0: return 0, '', '', False sys.stdout.write( 'Password: ' ) password = sys.stdin.readline().strip() save_password = 'x' while save_password.lower() not in ['y','ye','yes','n', 'no','']: sys.stdout.write( 'Save password? [y/n] ' ) save_password = sys.stdin.readline().strip() return 1, username, password, save_password in ['y','ye','yes'] def main(): if len(sys.argv) != 2: print 'Usage: %s version' % sys.argv[0] return version = sys.argv[1] from_url = 'https://svn.code.sf.net/p/cxx/code/trunk/CXX' tag_base_url = 'https://svn.code.sf.net/p/cxx/code/tags' make_tag( from_url, tag_base_url, version ) if __name__ == '__main__': main() pycxx-6.2.5/Src/cxx_extensions.cxx000644 000771 000000 00000004354 11146072165 017516 0ustar00barrywheel000000 000000 //----------------------------------------------------------------------------- // // Copyright (c) 1998 - 2007, The Regents of the University of California // Produced at the Lawrence Livermore National Laboratory // All rights reserved. // // This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The // full copyright notice is contained in the file COPYRIGHT located at the root // of the PyCXX distribution. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // - Redistributions of source code must retain the above copyright notice, // this list of conditions and the disclaimer below. // - Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the disclaimer (as noted below) in the // documentation and/or materials provided with the distribution. // - Neither the name of the UC/LLNL nor the names of its contributors may be // used to endorse or promote products derived from this software without // specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF // CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH // DAMAGE. // //----------------------------------------------------------------------------- #include "CXX/WrapPython.h" #if PY_MAJOR_VERSION == 2 #include "Python2/cxx_extensions.cxx" #else #include "Python3/cxx_extensions.cxx" #endif pycxx-6.2.5/Src/cxxextensions.c000644 000771 000000 00000004356 11146072165 017001 0ustar00barrywheel000000 000000 //----------------------------------------------------------------------------- // // Copyright (c) 1998 - 2007, The Regents of the University of California // Produced at the Lawrence Livermore National Laboratory // All rights reserved. // // This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The // full copyright notice is contained in the file COPYRIGHT located at the root // of the PyCXX distribution. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // - Redistributions of source code must retain the above copyright notice, // this list of conditions and the disclaimer below. // - Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the disclaimer (as noted below) in the // documentation and/or materials provided with the distribution. // - Neither the name of the UC/LLNL nor the names of its contributors may be // used to endorse or promote products derived from this software without // specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF // CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH // DAMAGE. // //----------------------------------------------------------------------------- #include "CXX/WrapPython.h" #if PY_MAJOR_VERSION == 2 #include "Src/Python2/cxxextensions.c" #else #include "Src/Python3/cxxextensions.c" #endif pycxx-6.2.5/Src/cxxsupport.cxx000644 000771 000000 00000004354 11146072165 016674 0ustar00barrywheel000000 000000 //----------------------------------------------------------------------------- // // Copyright (c) 1998 - 2007, The Regents of the University of California // Produced at the Lawrence Livermore National Laboratory // All rights reserved. // // This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The // full copyright notice is contained in the file COPYRIGHT located at the root // of the PyCXX distribution. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // - Redistributions of source code must retain the above copyright notice, // this list of conditions and the disclaimer below. // - Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the disclaimer (as noted below) in the // documentation and/or materials provided with the distribution. // - Neither the name of the UC/LLNL nor the names of its contributors may be // used to endorse or promote products derived from this software without // specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF // CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH // DAMAGE. // //----------------------------------------------------------------------------- #include "CXX/WrapPython.h" #if PY_MAJOR_VERSION == 2 #include "Src/Python2/cxxsupport.cxx" #else #include "Src/Python3/cxxsupport.cxx" #endif pycxx-6.2.5/Src/IndirectPythonInterface.cxx000644 000771 000000 00000061570 11541734710 021224 0ustar00barrywheel000000 000000 //----------------------------------------------------------------------------- // // Copyright (c) 1998 - 2007, The Regents of the University of California // Produced at the Lawrence Livermore National Laboratory // All rights reserved. // // This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The // full copyright notice is contained in the file COPYRIGHT located at the root // of the PyCXX distribution. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // - Redistributions of source code must retain the above copyright notice, // this list of conditions and the disclaimer below. // - Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the disclaimer (as noted below) in the // documentation and/or materials provided with the distribution. // - Neither the name of the UC/LLNL nor the names of its contributors may be // used to endorse or promote products derived from this software without // specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF // CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH // DAMAGE. // //----------------------------------------------------------------------------- #include "CXX/IndirectPythonInterface.hxx" namespace Py { bool _CFunction_Check( PyObject *op ) { return op->ob_type == _CFunction_Type(); } bool _Complex_Check( PyObject *op ) { return op->ob_type == _Complex_Type(); } bool _Dict_Check( PyObject *op ) { return op->ob_type == _Dict_Type(); } bool _Float_Check( PyObject *op ) { return op->ob_type == _Float_Type(); } bool _Function_Check( PyObject *op ) { return op->ob_type == _Function_Type(); } bool _Boolean_Check( PyObject *op ) { return op->ob_type == _Bool_Type(); } bool _List_Check( PyObject *op ) { return op->ob_type == _List_Type(); } bool _Long_Check( PyObject *op ) { return op->ob_type == _Long_Type(); } bool _Method_Check( PyObject *op ) { return op->ob_type == _Method_Type(); } bool _Module_Check( PyObject *op ) { return op->ob_type == _Module_Type(); } bool _Range_Check( PyObject *op ) { return op->ob_type == _Range_Type(); } bool _Slice_Check( PyObject *op ) { return op->ob_type == _Slice_Type(); } bool _TraceBack_Check( PyObject *op ) { return op->ob_type == _TraceBack_Type(); } bool _Tuple_Check( PyObject *op ) { return op->ob_type == _Tuple_Type(); } bool _Type_Check( PyObject *op ) { return op->ob_type == _Type_Type(); } bool _Unicode_Check( PyObject *op ) { return op->ob_type == _Unicode_Type(); } #if PY_MAJOR_VERSION == 2 bool _String_Check( PyObject *op ) { return op->ob_type == _String_Type(); } bool _Int_Check( PyObject *op ) { return op->ob_type == _Int_Type(); } bool _CObject_Check( PyObject *op ) { return op->ob_type == _CObject_Type(); } #endif #if PY_MAJOR_VERSION >= 3 bool _Bytes_Check( PyObject *op ) { return op->ob_type == _Bytes_Type(); } #endif #if defined(PY_WIN32_DELAYLOAD_PYTHON_DLL) #if defined(MS_WINDOWS) #include static HMODULE python_dll; static PyObject *ptr__Exc_ArithmeticError = NULL; static PyObject *ptr__Exc_AssertionError = NULL; static PyObject *ptr__Exc_AttributeError = NULL; static PyObject *ptr__Exc_EnvironmentError = NULL; static PyObject *ptr__Exc_EOFError = NULL; static PyObject *ptr__Exc_Exception = NULL; static PyObject *ptr__Exc_FloatingPointError = NULL; static PyObject *ptr__Exc_ImportError = NULL; static PyObject *ptr__Exc_IndexError = NULL; static PyObject *ptr__Exc_IOError = NULL; static PyObject *ptr__Exc_KeyboardInterrupt = NULL; static PyObject *ptr__Exc_KeyError = NULL; static PyObject *ptr__Exc_LookupError = NULL; static PyObject *ptr__Exc_MemoryError = NULL; static PyObject *ptr__Exc_NameError = NULL; static PyObject *ptr__Exc_NotImplementedError = NULL; static PyObject *ptr__Exc_OSError = NULL; static PyObject *ptr__Exc_OverflowError = NULL; static PyObject *ptr__Exc_RuntimeError = NULL; static PyObject *ptr__Exc_StandardError = NULL; static PyObject *ptr__Exc_SyntaxError = NULL; static PyObject *ptr__Exc_SystemError = NULL; static PyObject *ptr__Exc_SystemExit = NULL; static PyObject *ptr__Exc_TypeError = NULL; static PyObject *ptr__Exc_ValueError = NULL; static PyObject *ptr__Exc_ZeroDivisionError = NULL; #ifdef MS_WINDOWS static PyObject *ptr__Exc_WindowsError = NULL; #endif static PyObject *ptr__Exc_IndentationError = NULL; static PyObject *ptr__Exc_TabError = NULL; static PyObject *ptr__Exc_UnboundLocalError = NULL; static PyObject *ptr__Exc_UnicodeError = NULL; static PyObject *ptr__PyNone = NULL; static PyObject *ptr__PyFalse = NULL; static PyObject *ptr__PyTrue = NULL; static PyTypeObject *ptr__CFunction_Type = NULL; static PyTypeObject *ptr__Complex_Type = NULL; static PyTypeObject *ptr__Dict_Type = NULL; static PyTypeObject *ptr__Float_Type = NULL; static PyTypeObject *ptr__Function_Type = NULL; static PyTypeObject *ptr__Bool_Type = NULL; static PyTypeObject *ptr__List_Type = NULL; static PyTypeObject *ptr__Long_Type = NULL; static PyTypeObject *ptr__Method_Type = NULL; static PyTypeObject *ptr__Module_Type = NULL; static PyTypeObject *ptr__Range_Type = NULL; static PyTypeObject *ptr__Slice_Type = NULL; static PyTypeObject *ptr__TraceBack_Type = NULL; static PyTypeObject *ptr__Tuple_Type = NULL; static PyTypeObject *ptr__Type_Type = NULL; #if PY_MAJOR_VERSION == 2 static PyTypeObject *ptr__Int_Type = NULL; static PyTypeObject *ptr__String_Type = NULL; static PyTypeObject *ptr__CObject_Type = NULL; #endif #if PY_MAJOR_VERSION >= 3 static PyTypeObject *ptr__Bytes_Type = NULL; #endif static int *ptr_Py_DebugFlag = NULL; static int *ptr_Py_InteractiveFlag = NULL; static int *ptr_Py_OptimizeFlag = NULL; static int *ptr_Py_NoSiteFlag = NULL; static int *ptr_Py_VerboseFlag = NULL; static char **ptr__Py_PackageContext = NULL; #ifdef Py_REF_DEBUG int *ptr_Py_RefTotal; #endif //-------------------------------------------------------------------------------- class GetAddressException { public: GetAddressException( const char *_name ) : name( _name ) {} virtual ~GetAddressException() {} const char *name; }; //-------------------------------------------------------------------------------- static PyObject *GetPyObjectPointer_As_PyObjectPointer( const char *name ) { FARPROC addr = GetProcAddress( python_dll, name ); if( addr == NULL ) throw GetAddressException( name ); return *(PyObject **)addr; } static PyObject *GetPyObject_As_PyObjectPointer( const char *name ) { FARPROC addr = GetProcAddress( python_dll, name ); if( addr == NULL ) throw GetAddressException( name ); return (PyObject *)addr; } static PyTypeObject *GetPyTypeObjectPointer_As_PyTypeObjectPointer( const char *name ) { FARPROC addr = GetProcAddress( python_dll, name ); if( addr == NULL ) throw GetAddressException( name ); return *(PyTypeObject **)addr; } static PyTypeObject *GetPyTypeObject_As_PyTypeObjectPointer( const char *name ) { FARPROC addr = GetProcAddress( python_dll, name ); if( addr == NULL ) throw GetAddressException( name ); return (PyTypeObject *)addr; } static int *GetInt_as_IntPointer( const char *name ) { FARPROC addr = GetProcAddress( python_dll, name ); if( addr == NULL ) throw GetAddressException( name ); return (int *)addr; } static char **GetCharPointer_as_CharPointerPointer( const char *name ) { FARPROC addr = GetProcAddress( python_dll, name ); if( addr == NULL ) throw GetAddressException( name ); return (char **)addr; } #ifdef _DEBUG static const char python_dll_name_format[] = "PYTHON%1.1d%1.1d_D.DLL"; #else static const char python_dll_name_format[] = "PYTHON%1.1d%1.1d.DLL"; #endif //-------------------------------------------------------------------------------- bool InitialisePythonIndirectInterface() { char python_dll_name[sizeof(python_dll_name_format)]; _snprintf( python_dll_name, sizeof(python_dll_name_format) / sizeof(char) - 1, python_dll_name_format, PY_MAJOR_VERSION, PY_MINOR_VERSION ); python_dll = LoadLibraryA( python_dll_name ); if( python_dll == NULL ) return false; try { #ifdef Py_REF_DEBUG ptr_Py_RefTotal = GetInt_as_IntPointer( "_Py_RefTotal" ); #endif ptr_Py_DebugFlag = GetInt_as_IntPointer( "Py_DebugFlag" ); ptr_Py_InteractiveFlag = GetInt_as_IntPointer( "Py_InteractiveFlag" ); ptr_Py_OptimizeFlag = GetInt_as_IntPointer( "Py_OptimizeFlag" ); ptr_Py_NoSiteFlag = GetInt_as_IntPointer( "Py_NoSiteFlag" ); ptr_Py_VerboseFlag = GetInt_as_IntPointer( "Py_VerboseFlag" ); ptr__Py_PackageContext = GetCharPointer_as_CharPointerPointer( "_Py_PackageContext" ); ptr__Exc_ArithmeticError = GetPyObjectPointer_As_PyObjectPointer( "PyExc_ArithmeticError" ); ptr__Exc_AssertionError = GetPyObjectPointer_As_PyObjectPointer( "PyExc_AssertionError" ); ptr__Exc_AttributeError = GetPyObjectPointer_As_PyObjectPointer( "PyExc_AttributeError" ); ptr__Exc_EnvironmentError = GetPyObjectPointer_As_PyObjectPointer( "PyExc_EnvironmentError" ); ptr__Exc_EOFError = GetPyObjectPointer_As_PyObjectPointer( "PyExc_EOFError" ); ptr__Exc_Exception = GetPyObjectPointer_As_PyObjectPointer( "PyExc_Exception" ); ptr__Exc_FloatingPointError = GetPyObjectPointer_As_PyObjectPointer( "PyExc_FloatingPointError" ); ptr__Exc_ImportError = GetPyObjectPointer_As_PyObjectPointer( "PyExc_ImportError" ); ptr__Exc_IndexError = GetPyObjectPointer_As_PyObjectPointer( "PyExc_IndexError" ); ptr__Exc_IOError = GetPyObjectPointer_As_PyObjectPointer( "PyExc_IOError" ); ptr__Exc_KeyboardInterrupt = GetPyObjectPointer_As_PyObjectPointer( "PyExc_KeyboardInterrupt" ); ptr__Exc_KeyError = GetPyObjectPointer_As_PyObjectPointer( "PyExc_KeyError" ); ptr__Exc_LookupError = GetPyObjectPointer_As_PyObjectPointer( "PyExc_LookupError" ); ptr__Exc_MemoryError = GetPyObjectPointer_As_PyObjectPointer( "PyExc_MemoryError" ); ptr__Exc_NameError = GetPyObjectPointer_As_PyObjectPointer( "PyExc_NameError" ); ptr__Exc_NotImplementedError= GetPyObjectPointer_As_PyObjectPointer( "PyExc_NotImplementedError" ); ptr__Exc_OSError = GetPyObjectPointer_As_PyObjectPointer( "PyExc_OSError" ); ptr__Exc_OverflowError = GetPyObjectPointer_As_PyObjectPointer( "PyExc_OverflowError" ); ptr__Exc_RuntimeError = GetPyObjectPointer_As_PyObjectPointer( "PyExc_RuntimeError" ); ptr__Exc_StandardError = GetPyObjectPointer_As_PyObjectPointer( "PyExc_StandardError" ); ptr__Exc_SyntaxError = GetPyObjectPointer_As_PyObjectPointer( "PyExc_SyntaxError" ); ptr__Exc_SystemError = GetPyObjectPointer_As_PyObjectPointer( "PyExc_SystemError" ); ptr__Exc_SystemExit = GetPyObjectPointer_As_PyObjectPointer( "PyExc_SystemExit" ); ptr__Exc_TypeError = GetPyObjectPointer_As_PyObjectPointer( "PyExc_TypeError" ); ptr__Exc_ValueError = GetPyObjectPointer_As_PyObjectPointer( "PyExc_ValueError" ); #ifdef MS_WINDOWS ptr__Exc_WindowsError = GetPyObjectPointer_As_PyObjectPointer( "PyExc_WindowsError" ); #endif ptr__Exc_ZeroDivisionError = GetPyObjectPointer_As_PyObjectPointer( "PyExc_ZeroDivisionError" ); ptr__Exc_IndentationError = GetPyObjectPointer_As_PyObjectPointer( "PyExc_IndentationError" ); ptr__Exc_TabError = GetPyObjectPointer_As_PyObjectPointer( "PyExc_TabError" ); ptr__Exc_UnboundLocalError = GetPyObjectPointer_As_PyObjectPointer( "PyExc_UnboundLocalError" ); ptr__Exc_UnicodeError = GetPyObjectPointer_As_PyObjectPointer( "PyExc_UnicodeError" ); ptr__PyNone = GetPyObject_As_PyObjectPointer( "_Py_NoneStruct" ); ptr__PyFalse = GetPyObject_As_PyObjectPointer( "_Py_ZeroStruct" ); ptr__PyTrue = GetPyObject_As_PyObjectPointer( "_Py_TrueStruct" ); ptr__CFunction_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyCFunction_Type" ); ptr__Complex_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyComplex_Type" ); ptr__Dict_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyDict_Type" ); ptr__Float_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyFloat_Type" ); ptr__Function_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyFunction_Type" ); ptr__Bool_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyBool_Type" ); ptr__List_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyList_Type" ); ptr__Long_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyLong_Type" ); ptr__Method_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyMethod_Type" ); ptr__Module_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyModule_Type" ); ptr__Range_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyRange_Type" ); ptr__Slice_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PySlice_Type" ); ptr__TraceBack_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyTraceBack_Type" ); ptr__Tuple_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyTuple_Type" ); ptr__Type_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyType_Type" ); ptr__Unicode_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyUnicode_Type" ); #if PY_MAJOR_VERSION == 2 ptr__String_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyString_Type" ); ptr__Int_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyInt_Type" ); ptr__CObject_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyCObject_Type" ); #endif #if PY_MAJOR_VERSION >= 3 ptr__Bytes_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyBytes_Type" ); #endif } catch( GetAddressException &e ) { OutputDebugStringA( python_dll_name ); OutputDebugStringA( " does not contain symbol " ); OutputDebugStringA( e.name ); OutputDebugStringA( "\n" ); return false; } return true; } // // Wrap variables as function calls // PyObject *_Exc_ArithmeticError() { return ptr__Exc_ArithmeticError; } PyObject *_Exc_AssertionError() { return ptr__Exc_AssertionError; } PyObject *_Exc_AttributeError() { return ptr__Exc_AttributeError; } PyObject *_Exc_EnvironmentError() { return ptr__Exc_EnvironmentError; } PyObject *_Exc_EOFError() { return ptr__Exc_EOFError; } PyObject *_Exc_Exception() { return ptr__Exc_Exception; } PyObject *_Exc_FloatingPointError() { return ptr__Exc_FloatingPointError; } PyObject *_Exc_ImportError() { return ptr__Exc_ImportError; } PyObject *_Exc_IndexError() { return ptr__Exc_IndexError; } PyObject *_Exc_IOError() { return ptr__Exc_IOError; } PyObject *_Exc_KeyboardInterrupt() { return ptr__Exc_KeyboardInterrupt; } PyObject *_Exc_KeyError() { return ptr__Exc_KeyError; } PyObject *_Exc_LookupError() { return ptr__Exc_LookupError; } PyObject *_Exc_MemoryError() { return ptr__Exc_MemoryError; } PyObject *_Exc_NameError() { return ptr__Exc_NameError; } PyObject *_Exc_NotImplementedError() { return ptr__Exc_NotImplementedError; } PyObject *_Exc_OSError() { return ptr__Exc_OSError; } PyObject *_Exc_OverflowError() { return ptr__Exc_OverflowError; } PyObject *_Exc_RuntimeError() { return ptr__Exc_RuntimeError; } PyObject *_Exc_StandardError() { return ptr__Exc_StandardError; } PyObject *_Exc_SyntaxError() { return ptr__Exc_SyntaxError; } PyObject *_Exc_SystemError() { return ptr__Exc_SystemError; } PyObject *_Exc_SystemExit() { return ptr__Exc_SystemExit; } PyObject *_Exc_TypeError() { return ptr__Exc_TypeError; } PyObject *_Exc_ValueError() { return ptr__Exc_ValueError; } #ifdef MS_WINDOWS PyObject *_Exc_WindowsError() { return ptr__Exc_WindowsError; } #endif PyObject *_Exc_ZeroDivisionError() { return ptr__Exc_ZeroDivisionError; } PyObject *_Exc_IndentationError() { return ptr__Exc_IndentationError; } PyObject *_Exc_TabError() { return ptr__Exc_TabError; } PyObject *_Exc_UnboundLocalError() { return ptr__Exc_UnboundLocalError; } PyObject *_Exc_UnicodeError() { return ptr__Exc_UnicodeError; } // // wrap items in Object.h // PyObject *_None() { return ptr__PyNone; } PyObject *_False() { return ptr__PyFalse; } PyObject *_True() { return ptr__PyTrue; } PyTypeObject *_CFunction_Type() { return ptr__CFunction_Type; } PyTypeObject *_Complex_Type() { return ptr__Complex_Type; } PyTypeObject *_Dict_Type() { return ptr__Dict_Type; } PyTypeObject *_Float_Type() { return ptr__Float_Type; } PyTypeObject *_Function_Type() { return ptr__Function_Type; } PyTypeObject *_Bool_Type() { return ptr__Bool_Type; } PyTypeObject *_List_Type() { return ptr__List_Type; } PyTypeObject *_Long_Type() { return ptr__Long_Type; } PyTypeObject *_Method_Type() { return ptr__Method_Type; } PyTypeObject *_Module_Type() { return ptr__Module_Type; } PyTypeObject *_Range_Type() { return ptr__Range_Type; } PyTypeObject *_Slice_Type() { return ptr__Slice_Type; } PyTypeObject *_TraceBack_Type() { return ptr__TraceBack_Type; } PyTypeObject *_Tuple_Type() { return ptr__Tuple_Type; } PyTypeObject *_Type_Type() { return ptr__Type_Type; } PyTypeObject *_Unicode_Type() { return ptr__Unicode_Type; } #if PY_MAJOR_VERSION == 2 PyTypeObject *_String_Type() { return ptr__String_Type; } PyTypeObject *_Int_Type() { return ptr__Int_Type; } PyTypeObject *_CObject_Type() { return ptr__CObject_Type; } #endif #if PY_MAJOR_VERSION >= 3 PyTypeObject *_Bytes_Type() { return ptr__Bytes_Type; } #endif char *__Py_PackageContext() { return *ptr__Py_PackageContext; } // // wrap the Python Flag variables // int &_Py_DebugFlag() { return *ptr_Py_DebugFlag; } int &_Py_InteractiveFlag() { return *ptr_Py_InteractiveFlag; } int &_Py_OptimizeFlag() { return *ptr_Py_OptimizeFlag; } int &_Py_NoSiteFlag() { return *ptr_Py_NoSiteFlag; } int &_Py_VerboseFlag() { return *ptr_Py_VerboseFlag; } #if 0 #define Py_INCREF(op) ( \ _Py_INC_REFTOTAL _Py_REF_DEBUG_COMMA \ ((PyObject*)(op))->ob_refcnt++) #define Py_DECREF(op) \ if (_Py_DEC_REFTOTAL _Py_REF_DEBUG_COMMA \ --((PyObject*)(op))->ob_refcnt != 0) \ _Py_CHECK_REFCNT(op) \ else \ _Py_Dealloc((PyObject *)(op)) #endif void _XINCREF( PyObject *op ) { // This function must match the contents of Py_XINCREF(op) if( op == NULL ) return; #ifdef Py_REF_DEBUG (*ptr_Py_RefTotal)++; #endif (op)->ob_refcnt++; } void _XDECREF( PyObject *op ) { // This function must match the contents of Py_XDECREF(op); if( op == NULL ) return; #ifdef Py_REF_DEBUG (*ptr_Py_RefTotal)--; #endif if (--(op)->ob_refcnt == 0) _Py_Dealloc((PyObject *)(op)); } #else #error "Can only delay load under Win32" #endif #else //================================================================================ // // Map onto Macros // //================================================================================ // // Wrap variables as function calls // PyObject *_Exc_ArithmeticError() { return ::PyExc_ArithmeticError; } PyObject *_Exc_AssertionError() { return ::PyExc_AssertionError; } PyObject *_Exc_AttributeError() { return ::PyExc_AttributeError; } PyObject *_Exc_EnvironmentError() { return ::PyExc_EnvironmentError; } PyObject *_Exc_EOFError() { return ::PyExc_EOFError; } PyObject *_Exc_Exception() { return ::PyExc_Exception; } PyObject *_Exc_FloatingPointError() { return ::PyExc_FloatingPointError; } PyObject *_Exc_ImportError() { return ::PyExc_ImportError; } PyObject *_Exc_IndexError() { return ::PyExc_IndexError; } PyObject *_Exc_IOError() { return ::PyExc_IOError; } PyObject *_Exc_KeyboardInterrupt() { return ::PyExc_KeyboardInterrupt; } PyObject *_Exc_KeyError() { return ::PyExc_KeyError; } PyObject *_Exc_LookupError() { return ::PyExc_LookupError; } PyObject *_Exc_MemoryError() { return ::PyExc_MemoryError; } PyObject *_Exc_NameError() { return ::PyExc_NameError; } PyObject *_Exc_NotImplementedError() { return ::PyExc_NotImplementedError; } PyObject *_Exc_OSError() { return ::PyExc_OSError; } PyObject *_Exc_OverflowError() { return ::PyExc_OverflowError; } PyObject *_Exc_RuntimeError() { return ::PyExc_RuntimeError; } PyObject *_Exc_SyntaxError() { return ::PyExc_SyntaxError; } PyObject *_Exc_SystemError() { return ::PyExc_SystemError; } PyObject *_Exc_SystemExit() { return ::PyExc_SystemExit; } PyObject *_Exc_TypeError() { return ::PyExc_TypeError; } PyObject *_Exc_ValueError() { return ::PyExc_ValueError; } PyObject *_Exc_ZeroDivisionError() { return ::PyExc_ZeroDivisionError; } PyObject *_Exc_IndentationError() { return ::PyExc_IndentationError; } PyObject *_Exc_TabError() { return ::PyExc_TabError; } PyObject *_Exc_UnboundLocalError() { return ::PyExc_UnboundLocalError; } PyObject *_Exc_UnicodeError() { return ::PyExc_UnicodeError; } #ifdef MS_WINDOWS PyObject *_Exc_WindowsError() { return ::PyExc_WindowsError; } #endif // // wrap items in Object.h // PyObject *_None() { return &::_Py_NoneStruct; } PyObject *_False() { return Py_False; } PyObject *_True() { return Py_True; } PyTypeObject *_CFunction_Type() { return &PyCFunction_Type; } PyTypeObject *_Complex_Type() { return &PyComplex_Type; } PyTypeObject *_Dict_Type() { return &PyDict_Type; } PyTypeObject *_Float_Type() { return &PyFloat_Type; } PyTypeObject *_Function_Type() { return &PyFunction_Type; } PyTypeObject *_Bool_Type() { return &PyBool_Type; } PyTypeObject *_List_Type() { return &PyList_Type; } PyTypeObject *_Long_Type() { return &PyLong_Type; } PyTypeObject *_Method_Type() { return &PyMethod_Type; } PyTypeObject *_Module_Type() { return &PyModule_Type; } PyTypeObject *_Range_Type() { return &PyRange_Type; } PyTypeObject *_Slice_Type() { return &PySlice_Type; } PyTypeObject *_TraceBack_Type() { return &PyTraceBack_Type; } PyTypeObject *_Tuple_Type() { return &PyTuple_Type; } PyTypeObject *_Type_Type() { return &PyType_Type; } PyTypeObject *_Unicode_Type() { return &PyUnicode_Type; } #if PY_MAJOR_VERSION == 2 PyTypeObject *_String_Type() { return &PyString_Type; } PyTypeObject *_Int_Type() { return &PyInt_Type; } PyTypeObject *_CObject_Type() { return &PyCObject_Type; } #endif #if PY_MAJOR_VERSION >= 3 PyTypeObject *_Bytes_Type() { return &PyBytes_Type; } #endif // // wrap flags // int &_Py_DebugFlag() { return Py_DebugFlag; } int &_Py_InteractiveFlag() { return Py_InteractiveFlag; } int &_Py_OptimizeFlag() { return Py_OptimizeFlag; } int &_Py_NoSiteFlag() { return Py_NoSiteFlag; } int &_Py_VerboseFlag() { return Py_VerboseFlag; } char *__Py_PackageContext() { return _Py_PackageContext; } // // Needed to keep the abstactions for delayload interface // void _XINCREF( PyObject *op ) { Py_XINCREF( op ); } void _XDECREF( PyObject *op ) { Py_XDECREF( op ); } #endif } pycxx-6.2.5/Src/Python2/000755 000771 000000 00000000000 12204160454 015241 5ustar00barrywheel000000 000000 pycxx-6.2.5/Src/Python3/000755 000771 000000 00000000000 12204160454 015242 5ustar00barrywheel000000 000000 pycxx-6.2.5/Src/Python3/cxx_extensions.cxx000644 000771 000000 00000142147 12160124644 021062 0ustar00barrywheel000000 000000 //----------------------------------------------------------------------------- // // Copyright (c) 1998 - 2007, The Regents of the University of California // Produced at the Lawrence Livermore National Laboratory // All rights reserved. // // This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The // full copyright notice is contained in the file COPYRIGHT located at the root // of the PyCXX distribution. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // - Redistributions of source code must retain the above copyright notice, // this list of conditions and the disclaimer below. // - Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the disclaimer (as noted below) in the // documentation and/or materials provided with the distribution. // - Neither the name of the UC/LLNL nor the names of its contributors may be // used to endorse or promote products derived from this software without // specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF // CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH // DAMAGE. // //----------------------------------------------------------------------------- #include "CXX/Extensions.hxx" #include "CXX/Exception.hxx" #include #ifdef PYCXX_DEBUG // // Functions useful when debugging PyCXX // void bpt( void ) { } void printRefCount( PyObject *obj ) { std::cout << "RefCount of 0x" << std::hex << reinterpret_cast< unsigned int >( obj ) << std::dec << " is " << Py_REFCNT( obj ) << std::endl; } #endif namespace Py { void Object::validate() { // release pointer if not the right type if( !accepts( p ) ) { #if defined( _CPPRTTI ) || defined( __GNUG__ ) std::string s( "PyCXX: Error creating object of type " ); s += (typeid( *this )).name(); if( p != NULL ) { String from_repr = repr(); s += " from "; s += from_repr.as_std_string(); } else { s += " from (nil)"; } #endif release(); if( PyErr_Occurred() ) { // Error message already set throw Exception(); } // Better error message if RTTI available #if defined( _CPPRTTI ) || defined( __GNUG__ ) throw TypeError( s ); #else throw TypeError( "PyCXX: type error." ); #endif } } //================================================================================ // // Implementation of MethodTable // //================================================================================ PyMethodDef MethodTable::method( const char *method_name, PyCFunction f, int flags, const char *doc ) { PyMethodDef m; m.ml_name = const_cast( method_name ); m.ml_meth = f; m.ml_flags = flags; m.ml_doc = const_cast( doc ); return m; } MethodTable::MethodTable() { t.push_back( method( 0, 0, 0, 0 ) ); mt = NULL; } MethodTable::~MethodTable() { delete [] mt; } void MethodTable::add( const char *method_name, PyCFunction f, const char *doc, int flag ) { if( !mt ) { t.insert( t.end()-1, method( method_name, f, flag, doc ) ); } else { throw RuntimeError( "Too late to add a module method!" ); } } PyMethodDef *MethodTable::table() { if( !mt ) { Py_ssize_t t1size = t.size(); mt = new PyMethodDef[ t1size ]; int j = 0; for( std::vector::iterator i = t.begin(); i != t.end(); i++ ) { mt[ j++ ] = *i; } } return mt; } //================================================================================ // // Implementation of ExtensionModule // //================================================================================ ExtensionModuleBase::ExtensionModuleBase( const char *name ) : m_module_name( name ) , m_full_module_name( __Py_PackageContext() != NULL ? std::string( __Py_PackageContext() ) : m_module_name ) , m_method_table() //m_module_def , m_module( NULL ) {} ExtensionModuleBase::~ExtensionModuleBase() {} const std::string &ExtensionModuleBase::name() const { return m_module_name; } const std::string &ExtensionModuleBase::fullName() const { return m_full_module_name; } class ExtensionModuleBasePtr : public PythonExtension { public: ExtensionModuleBasePtr( ExtensionModuleBase *_module ) : module( _module ) {} virtual ~ExtensionModuleBasePtr() {} ExtensionModuleBase *module; }; void ExtensionModuleBase::initialize( const char *module_doc ) { memset( &m_module_def, 0, sizeof( m_module_def ) ); m_module_def.m_name = const_cast( m_module_name.c_str() ); m_module_def.m_doc = const_cast( module_doc ); m_module_def.m_methods = m_method_table.table(); // where does module_ptr get passed in? m_module = PyModule_Create( &m_module_def ); } Py::Module ExtensionModuleBase::module( void ) const { return Module( m_module ); } Py::Dict ExtensionModuleBase::moduleDictionary( void ) const { return module().getDict(); } //================================================================================ // // Implementation of PythonType // //================================================================================ extern "C" { static void standard_dealloc( PyObject *p ); // // All the following functions redirect the call from Python // onto the matching virtual function in PythonExtensionBase // static int print_handler( PyObject *, FILE *, int ); static PyObject *getattr_handler( PyObject *, char * ); static int setattr_handler( PyObject *, char *, PyObject * ); static PyObject *getattro_handler( PyObject *, PyObject * ); static int setattro_handler( PyObject *, PyObject *, PyObject * ); static PyObject *rich_compare_handler( PyObject *, PyObject *, int ); static PyObject *repr_handler( PyObject * ); static PyObject *str_handler( PyObject * ); static Py_hash_t hash_handler( PyObject * ); static PyObject *call_handler( PyObject *, PyObject *, PyObject * ); static PyObject *iter_handler( PyObject * ); static PyObject *iternext_handler( PyObject * ); // Sequence methods static Py_ssize_t sequence_length_handler( PyObject * ); static PyObject *sequence_concat_handler( PyObject *,PyObject * ); static PyObject *sequence_repeat_handler( PyObject *, Py_ssize_t ); static PyObject *sequence_item_handler( PyObject *, Py_ssize_t ); static int sequence_ass_item_handler( PyObject *, Py_ssize_t, PyObject * ); // Mapping static Py_ssize_t mapping_length_handler( PyObject * ); static PyObject *mapping_subscript_handler( PyObject *, PyObject * ); static int mapping_ass_subscript_handler( PyObject *, PyObject *, PyObject * ); // Numeric methods static PyObject *number_negative_handler( PyObject * ); static PyObject *number_positive_handler( PyObject * ); static PyObject *number_absolute_handler( PyObject * ); static PyObject *number_invert_handler( PyObject * ); static PyObject *number_int_handler( PyObject * ); static PyObject *number_float_handler( PyObject * ); static PyObject *number_add_handler( PyObject *, PyObject * ); static PyObject *number_subtract_handler( PyObject *, PyObject * ); static PyObject *number_multiply_handler( PyObject *, PyObject * ); static PyObject *number_remainder_handler( PyObject *, PyObject * ); static PyObject *number_divmod_handler( PyObject *, PyObject * ); static PyObject *number_lshift_handler( PyObject *, PyObject * ); static PyObject *number_rshift_handler( PyObject *, PyObject * ); static PyObject *number_and_handler( PyObject *, PyObject * ); static PyObject *number_xor_handler( PyObject *, PyObject * ); static PyObject *number_or_handler( PyObject *, PyObject * ); static PyObject *number_power_handler( PyObject *, PyObject *, PyObject * ); // Buffer static int buffer_get_handler( PyObject *, Py_buffer *, int ); static void buffer_release_handler( PyObject *, Py_buffer * ); } extern "C" void standard_dealloc( PyObject *p ) { PyMem_DEL( p ); } bool PythonType::readyType() { return PyType_Ready( table ) >= 0; } PythonType &PythonType::supportSequenceType() { if( !sequence_table ) { sequence_table = new PySequenceMethods; memset( sequence_table, 0, sizeof( PySequenceMethods ) ); // ensure new fields are 0 table->tp_as_sequence = sequence_table; sequence_table->sq_length = sequence_length_handler; sequence_table->sq_concat = sequence_concat_handler; sequence_table->sq_repeat = sequence_repeat_handler; sequence_table->sq_item = sequence_item_handler; sequence_table->sq_ass_item = sequence_ass_item_handler; // BAS setup seperately? // QQQ sq_inplace_concat // QQQ sq_inplace_repeat } return *this; } PythonType &PythonType::supportMappingType() { if( !mapping_table ) { mapping_table = new PyMappingMethods; memset( mapping_table, 0, sizeof( PyMappingMethods ) ); // ensure new fields are 0 table->tp_as_mapping = mapping_table; mapping_table->mp_length = mapping_length_handler; mapping_table->mp_subscript = mapping_subscript_handler; mapping_table->mp_ass_subscript = mapping_ass_subscript_handler; // BAS setup seperately? } return *this; } PythonType &PythonType::supportNumberType() { if( !number_table ) { number_table = new PyNumberMethods; memset( number_table, 0, sizeof( PyNumberMethods ) ); // ensure new fields are 0 table->tp_as_number = number_table; number_table->nb_add = number_add_handler; number_table->nb_subtract = number_subtract_handler; number_table->nb_multiply = number_multiply_handler; number_table->nb_remainder = number_remainder_handler; number_table->nb_divmod = number_divmod_handler; number_table->nb_power = number_power_handler; number_table->nb_negative = number_negative_handler; number_table->nb_positive = number_positive_handler; number_table->nb_absolute = number_absolute_handler; number_table->nb_invert = number_invert_handler; number_table->nb_lshift = number_lshift_handler; number_table->nb_rshift = number_rshift_handler; number_table->nb_and = number_and_handler; number_table->nb_xor = number_xor_handler; number_table->nb_or = number_or_handler; number_table->nb_int = number_int_handler; number_table->nb_float = number_float_handler; // QQQ lots of new methods to add } return *this; } PythonType &PythonType::supportBufferType() { if( !buffer_table ) { buffer_table = new PyBufferProcs; memset( buffer_table, 0, sizeof( PyBufferProcs ) ); // ensure new fields are 0 table->tp_as_buffer = buffer_table; buffer_table->bf_getbuffer = buffer_get_handler; buffer_table->bf_releasebuffer = buffer_release_handler; } return *this; } // if you define one sequence method you must define // all of them except the assigns PythonType::PythonType( size_t basic_size, int itemsize, const char *default_name ) : table( new PyTypeObject ) , sequence_table( NULL ) , mapping_table( NULL ) , number_table( NULL ) , buffer_table( NULL ) { // PyTypeObject is defined in /Include/object.h memset( table, 0, sizeof( PyTypeObject ) ); // ensure new fields are 0 *reinterpret_cast( table ) = py_object_initializer; reinterpret_cast( table )->ob_type = _Type_Type(); // QQQ table->ob_size = 0; table->tp_name = const_cast( default_name ); table->tp_basicsize = basic_size; table->tp_itemsize = itemsize; // Methods to implement standard operations table->tp_dealloc = (destructor)standard_dealloc; table->tp_print = 0; table->tp_getattr = 0; table->tp_setattr = 0; table->tp_repr = 0; // Method suites for standard classes table->tp_as_number = 0; table->tp_as_sequence = 0; table->tp_as_mapping = 0; // More standard operations (here for binary compatibility) table->tp_hash = 0; table->tp_call = 0; table->tp_str = 0; table->tp_getattro = 0; table->tp_setattro = 0; // Functions to access object as input/output buffer table->tp_as_buffer = 0; // Flags to define presence of optional/expanded features table->tp_flags = Py_TPFLAGS_DEFAULT; // Documentation string table->tp_doc = 0; table->tp_traverse = 0; // delete references to contained objects table->tp_clear = 0; // Assigned meaning in release 2.1 // rich comparisons table->tp_richcompare = 0; // weak reference enabler table->tp_weaklistoffset = 0; // Iterators table->tp_iter = 0; table->tp_iternext = 0; // Attribute descriptor and subclassing stuff table->tp_methods = 0; table->tp_members = 0; table->tp_getset = 0; table->tp_base = 0; table->tp_dict = 0; table->tp_descr_get = 0; table->tp_descr_set = 0; table->tp_dictoffset = 0; table->tp_init = 0; table->tp_alloc = 0; table->tp_new = 0; table->tp_free = 0; // Low-level free-memory routine table->tp_is_gc = 0; // For PyObject_IS_GC table->tp_bases = 0; table->tp_mro = 0; // method resolution order table->tp_cache = 0; table->tp_subclasses = 0; table->tp_weaklist = 0; table->tp_del = 0; // Type attribute cache version tag. Added in version 2.6 table->tp_version_tag = 0; #ifdef COUNT_ALLOCS table->tp_alloc = 0; table->tp_free = 0; table->tp_maxalloc = 0; table->tp_orev = 0; table->tp_next = 0; #endif } PythonType::~PythonType() { delete table; delete sequence_table; delete mapping_table; delete number_table; delete buffer_table; } PyTypeObject *PythonType::type_object() const { return table; } PythonType &PythonType::name( const char *nam ) { table->tp_name = const_cast( nam ); return *this; } const char *PythonType::getName() const { return table->tp_name; } PythonType &PythonType::doc( const char *d ) { table->tp_doc = const_cast( d ); return *this; } const char *PythonType::getDoc() const { return table->tp_doc; } PythonType &PythonType::set_tp_dealloc( void (*tp_dealloc)( PyObject *self ) ) { table->tp_dealloc = tp_dealloc; return *this; } PythonType &PythonType::set_tp_init( int (*tp_init)( PyObject *self, PyObject *args, PyObject *kwds ) ) { table->tp_init = tp_init; return *this; } PythonType &PythonType::set_tp_new( PyObject *(*tp_new)( PyTypeObject *subtype, PyObject *args, PyObject *kwds ) ) { table->tp_new = tp_new; return *this; } PythonType &PythonType::set_methods( PyMethodDef *methods ) { table->tp_methods = methods; return *this; } PythonType &PythonType::supportClass() { table->tp_flags |= Py_TPFLAGS_BASETYPE; return *this; } #ifdef PYCXX_PYTHON_2TO3 PythonType &PythonType::supportPrint() { table->tp_print = print_handler; return *this; } #endif PythonType &PythonType::supportGetattr() { table->tp_getattr = getattr_handler; return *this; } PythonType &PythonType::supportSetattr() { table->tp_setattr = setattr_handler; return *this; } PythonType &PythonType::supportGetattro() { table->tp_getattro = getattro_handler; return *this; } PythonType &PythonType::supportSetattro() { table->tp_setattro = setattro_handler; return *this; } #ifdef PYCXX_PYTHON_2TO3 PythonType &PythonType::supportCompare( void ) { return *this; } #endif PythonType &PythonType::supportRichCompare() { table->tp_richcompare = rich_compare_handler; return *this; } PythonType &PythonType::supportRepr() { table->tp_repr = repr_handler; return *this; } PythonType &PythonType::supportStr() { table->tp_str = str_handler; return *this; } PythonType &PythonType::supportHash() { table->tp_hash = hash_handler; return *this; } PythonType &PythonType::supportCall() { table->tp_call = call_handler; return *this; } PythonType &PythonType::supportIter() { table->tp_iter = iter_handler; table->tp_iternext = iternext_handler; return *this; } //-------------------------------------------------------------------------------- // // Handlers // //-------------------------------------------------------------------------------- PythonExtensionBase *getPythonExtensionBase( PyObject *self ) { if( self->ob_type->tp_flags&Py_TPFLAGS_BASETYPE ) { PythonClassInstance *instance = reinterpret_cast( self ); return instance->m_pycxx_object; } else { return static_cast( self ); } } #ifdef PYCXX_PYTHON_2TO3 extern "C" int print_handler( PyObject *self, FILE *fp, int flags ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return p->print( fp, flags ); } catch( Py::Exception & ) { return -1; // indicate error } } #endif extern "C" PyObject *getattr_handler( PyObject *self, char *name ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return new_reference_to( p->getattr( name ) ); } catch( Py::Exception & ) { return NULL; // indicate error } } extern "C" int setattr_handler( PyObject *self, char *name, PyObject *value ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return p->setattr( name, Py::Object( value ) ); } catch( Py::Exception & ) { return -1; // indicate error } } extern "C" PyObject *getattro_handler( PyObject *self, PyObject *name ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return new_reference_to( p->getattro( Py::String( name ) ) ); } catch( Py::Exception & ) { return NULL; // indicate error } } extern "C" int setattro_handler( PyObject *self, PyObject *name, PyObject *value ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return p->setattro( Py::String( name ), Py::Object( value ) ); } catch( Py::Exception & ) { return -1; // indicate error } } extern "C" PyObject *rich_compare_handler( PyObject *self, PyObject *other, int op ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return new_reference_to( p->rich_compare( Py::Object( other ), op ) ); } catch( Py::Exception & ) { return NULL; // indicate error } } extern "C" PyObject *repr_handler( PyObject *self ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return new_reference_to( p->repr() ); } catch( Py::Exception & ) { return NULL; // indicate error } } extern "C" PyObject *str_handler( PyObject *self ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return new_reference_to( p->str() ); } catch( Py::Exception & ) { return NULL; // indicate error } } extern "C" Py_hash_t hash_handler( PyObject *self ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return p->hash(); } catch( Py::Exception & ) { return -1; // indicate error } } extern "C" PyObject *call_handler( PyObject *self, PyObject *args, PyObject *kw ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); if( kw != NULL ) return new_reference_to( p->call( Py::Object( args ), Py::Object( kw ) ) ); else return new_reference_to( p->call( Py::Object( args ), Py::Object() ) ); } catch( Py::Exception & ) { return NULL; // indicate error } } extern "C" PyObject *iter_handler( PyObject *self ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return new_reference_to( p->iter() ); } catch( Py::Exception & ) { return NULL; // indicate error } } extern "C" PyObject *iternext_handler( PyObject *self ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return p->iternext(); // might be a NULL ptr on end of iteration } catch( Py::Exception & ) { return NULL; // indicate error } } // Sequence methods extern "C" Py_ssize_t sequence_length_handler( PyObject *self ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return p->sequence_length(); } catch( Py::Exception & ) { return -1; // indicate error } } extern "C" PyObject *sequence_concat_handler( PyObject *self, PyObject *other ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return new_reference_to( p->sequence_concat( Py::Object( other ) ) ); } catch( Py::Exception & ) { return NULL; // indicate error } } extern "C" PyObject *sequence_repeat_handler( PyObject *self, Py_ssize_t count ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return new_reference_to( p->sequence_repeat( count ) ); } catch( Py::Exception & ) { return NULL; // indicate error } } extern "C" PyObject *sequence_item_handler( PyObject *self, Py_ssize_t index ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return new_reference_to( p->sequence_item( index ) ); } catch( Py::Exception & ) { return NULL; // indicate error } } extern "C" int sequence_ass_item_handler( PyObject *self, Py_ssize_t index, PyObject *value ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return p->sequence_ass_item( index, Py::Object( value ) ); } catch( Py::Exception & ) { return -1; // indicate error } } // Mapping extern "C" Py_ssize_t mapping_length_handler( PyObject *self ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return p->mapping_length(); } catch( Py::Exception & ) { return -1; // indicate error } } extern "C" PyObject *mapping_subscript_handler( PyObject *self, PyObject *key ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return new_reference_to( p->mapping_subscript( Py::Object( key ) ) ); } catch( Py::Exception & ) { return NULL; // indicate error } } extern "C" int mapping_ass_subscript_handler( PyObject *self, PyObject *key, PyObject *value ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return p->mapping_ass_subscript( Py::Object( key ), Py::Object( value ) ); } catch( Py::Exception & ) { return -1; // indicate error } } // Number extern "C" PyObject *number_negative_handler( PyObject *self ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return new_reference_to( p->number_negative() ); } catch( Py::Exception & ) { return NULL; // indicate error } } extern "C" PyObject *number_positive_handler( PyObject *self ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return new_reference_to( p->number_positive() ); } catch( Py::Exception & ) { return NULL; // indicate error } } extern "C" PyObject *number_absolute_handler( PyObject *self ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return new_reference_to( p->number_absolute() ); } catch( Py::Exception & ) { return NULL; // indicate error } } extern "C" PyObject *number_invert_handler( PyObject *self ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return new_reference_to( p->number_invert() ); } catch( Py::Exception & ) { return NULL; // indicate error } } extern "C" PyObject *number_int_handler( PyObject *self ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return new_reference_to( p->number_int() ); } catch( Py::Exception & ) { return NULL; // indicate error } } extern "C" PyObject *number_float_handler( PyObject *self ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return new_reference_to( p->number_float() ); } catch( Py::Exception & ) { return NULL; // indicate error } } extern "C" PyObject *number_add_handler( PyObject *self, PyObject *other ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return new_reference_to( p->number_add( Py::Object( other ) ) ); } catch( Py::Exception & ) { return NULL; // indicate error } } extern "C" PyObject *number_subtract_handler( PyObject *self, PyObject *other ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return new_reference_to( p->number_subtract( Py::Object( other ) ) ); } catch( Py::Exception & ) { return NULL; // indicate error } } extern "C" PyObject *number_multiply_handler( PyObject *self, PyObject *other ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return new_reference_to( p->number_multiply( Py::Object( other ) ) ); } catch( Py::Exception & ) { return NULL; // indicate error } } extern "C" PyObject *number_remainder_handler( PyObject *self, PyObject *other ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return new_reference_to( p->number_remainder( Py::Object( other ) ) ); } catch( Py::Exception & ) { return NULL; // indicate error } } extern "C" PyObject *number_divmod_handler( PyObject *self, PyObject *other ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return new_reference_to( p->number_divmod( Py::Object( other ) ) ); } catch( Py::Exception & ) { return NULL; // indicate error } } extern "C" PyObject *number_lshift_handler( PyObject *self, PyObject *other ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return new_reference_to( p->number_lshift( Py::Object( other ) ) ); } catch( Py::Exception & ) { return NULL; // indicate error } } extern "C" PyObject *number_rshift_handler( PyObject *self, PyObject *other ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return new_reference_to( p->number_rshift( Py::Object( other ) ) ); } catch( Py::Exception & ) { return NULL; // indicate error } } extern "C" PyObject *number_and_handler( PyObject *self, PyObject *other ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return new_reference_to( p->number_and( Py::Object( other ) ) ); } catch( Py::Exception & ) { return NULL; // indicate error } } extern "C" PyObject *number_xor_handler( PyObject *self, PyObject *other ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return new_reference_to( p->number_xor( Py::Object( other ) ) ); } catch( Py::Exception & ) { return NULL; // indicate error } } extern "C" PyObject *number_or_handler( PyObject *self, PyObject *other ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return new_reference_to( p->number_or( Py::Object( other ) ) ); } catch( Py::Exception & ) { return NULL; // indicate error } } extern "C" PyObject *number_power_handler( PyObject *self, PyObject *x1, PyObject *x2 ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return new_reference_to( p->number_power( Py::Object( x1 ), Py::Object( x2 ) ) ); } catch( Py::Exception & ) { return NULL; // indicate error } } // Buffer extern "C" int buffer_get_handler( PyObject *self, Py_buffer *buf, int flags ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return p->buffer_get( buf, flags ); } catch( Py::Exception & ) { return -1; // indicate error } } extern "C" void buffer_release_handler( PyObject *self, Py_buffer *buf ) { PythonExtensionBase *p = getPythonExtensionBase( self ); p->buffer_release( buf ); // NOTE: No way to indicate error to Python } //================================================================================ // // Implementation of PythonExtensionBase // //================================================================================ #define missing_method( method ) \ throw RuntimeError( "Extension object missing implement of " #method ); PythonExtensionBase::PythonExtensionBase() { ob_refcnt = 0; } PythonExtensionBase::~PythonExtensionBase() { assert( ob_refcnt == 0 ); } Py::Object PythonExtensionBase::callOnSelf( const std::string &fn_name ) { Py::TupleN args; return self().callMemberFunction( fn_name, args ); } Py::Object PythonExtensionBase::callOnSelf( const std::string &fn_name, const Py::Object &arg1 ) { Py::TupleN args( arg1 ); return self().callMemberFunction( fn_name, args ); } Py::Object PythonExtensionBase::callOnSelf( const std::string &fn_name, const Py::Object &arg1, const Py::Object &arg2 ) { Py::TupleN args( arg1, arg2 ); return self().callMemberFunction( fn_name, args ); } Py::Object PythonExtensionBase::callOnSelf( const std::string &fn_name, const Py::Object &arg1, const Py::Object &arg2, const Py::Object &arg3 ) { Py::TupleN args( arg1, arg2, arg3 ); return self().callMemberFunction( fn_name, args ); } Py::Object PythonExtensionBase::callOnSelf( const std::string &fn_name, const Py::Object &arg1, const Py::Object &arg2, const Py::Object &arg3, const Py::Object &arg4 ) { Py::TupleN args( arg1, arg2, arg3, arg4 ); return self().callMemberFunction( fn_name, args ); } Py::Object PythonExtensionBase::callOnSelf( const std::string &fn_name, const Py::Object &arg1, const Py::Object &arg2, const Py::Object &arg3, const Py::Object &arg4, const Py::Object &arg5 ) { Py::TupleN args( arg1, arg2, arg3, arg4, arg5 ); return self().callMemberFunction( fn_name, args ); } Py::Object PythonExtensionBase::callOnSelf( const std::string &fn_name, const Py::Object &arg1, const Py::Object &arg2, const Py::Object &arg3, const Py::Object &arg4, const Py::Object &arg5, const Py::Object &arg6 ) { Py::TupleN args( arg1, arg2, arg3, arg4, arg5, arg6 ); return self().callMemberFunction( fn_name, args ); } Py::Object PythonExtensionBase::callOnSelf( const std::string &fn_name, const Py::Object &arg1, const Py::Object &arg2, const Py::Object &arg3, const Py::Object &arg4, const Py::Object &arg5, const Py::Object &arg6, const Py::Object &arg7 ) { Py::TupleN args( arg1, arg2, arg3, arg4, arg5, arg6, arg7 ); return self().callMemberFunction( fn_name, args ); } Py::Object PythonExtensionBase::callOnSelf( const std::string &fn_name, const Py::Object &arg1, const Py::Object &arg2, const Py::Object &arg3, const Py::Object &arg4, const Py::Object &arg5, const Py::Object &arg6, const Py::Object &arg7, const Py::Object &arg8 ) { Py::TupleN args( arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8 ); return self().callMemberFunction( fn_name, args ); } Py::Object PythonExtensionBase::callOnSelf( const std::string &fn_name, const Py::Object &arg1, const Py::Object &arg2, const Py::Object &arg3, const Py::Object &arg4, const Py::Object &arg5, const Py::Object &arg6, const Py::Object &arg7, const Py::Object &arg8, const Py::Object &arg9 ) { Py::TupleN args( arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9 ); return self().callMemberFunction( fn_name, args ); } void PythonExtensionBase::reinit( Tuple &args, Dict &kwds ) { throw RuntimeError( "Must not call __init__ twice on this class" ); } Py::Object PythonExtensionBase::genericGetAttro( const Py::String &name ) { return asObject( PyObject_GenericGetAttr( selfPtr(), name.ptr() ) ); } int PythonExtensionBase::genericSetAttro( const Py::String &name, const Py::Object &value ) { return PyObject_GenericSetAttr( selfPtr(), name.ptr(), value.ptr() ); } #ifdef PYCXX_PYTHON_2TO3 int PythonExtensionBase::print( FILE *, int ) { missing_method( print ); return -1; } #endif Py::Object PythonExtensionBase::getattr( const char * ) { missing_method( getattr ); return Py::None(); } int PythonExtensionBase::setattr( const char *, const Py::Object & ) { missing_method( setattr ); return -1; } Py::Object PythonExtensionBase::getattro( const Py::String &name ) { return asObject( PyObject_GenericGetAttr( selfPtr(), name.ptr() ) ); } int PythonExtensionBase::setattro( const Py::String &name, const Py::Object &value ) { return PyObject_GenericSetAttr( selfPtr(), name.ptr(), value.ptr() ); } int PythonExtensionBase::compare( const Py::Object & ) { missing_method( compare ); return -1; } Py::Object PythonExtensionBase::rich_compare( const Py::Object &, int ) { missing_method( rich_compare ); return Py::None(); } Py::Object PythonExtensionBase::repr() { missing_method( repr ); return Py::None(); } Py::Object PythonExtensionBase::str() { missing_method( str ); return Py::None(); } long PythonExtensionBase::hash() { missing_method( hash ); return -1; } Py::Object PythonExtensionBase::call( const Py::Object &, const Py::Object & ) { missing_method( call ); return Py::None(); } Py::Object PythonExtensionBase::iter() { missing_method( iter ); return Py::None(); } PyObject *PythonExtensionBase::iternext() { missing_method( iternext ); return NULL; } // Sequence methods int PythonExtensionBase::sequence_length() { missing_method( sequence_length ); return -1; } Py::Object PythonExtensionBase::sequence_concat( const Py::Object & ) { missing_method( sequence_concat ); return Py::None(); } Py::Object PythonExtensionBase::sequence_repeat( Py_ssize_t ) { missing_method( sequence_repeat ); return Py::None(); } Py::Object PythonExtensionBase::sequence_item( Py_ssize_t ) { missing_method( sequence_item ); return Py::None(); } int PythonExtensionBase::sequence_ass_item( Py_ssize_t, const Py::Object & ) { missing_method( sequence_ass_item ); return -1; } // Mapping int PythonExtensionBase::mapping_length() { missing_method( mapping_length ); return -1; } Py::Object PythonExtensionBase::mapping_subscript( const Py::Object & ) { missing_method( mapping_subscript ); return Py::None(); } int PythonExtensionBase::mapping_ass_subscript( const Py::Object &, const Py::Object & ) { missing_method( mapping_ass_subscript ); return -1; } Py::Object PythonExtensionBase::number_negative() { missing_method( number_negative ); return Py::None(); } Py::Object PythonExtensionBase::number_positive() { missing_method( number_positive ); return Py::None(); } Py::Object PythonExtensionBase::number_absolute() { missing_method( number_absolute ); return Py::None(); } Py::Object PythonExtensionBase::number_invert() { missing_method( number_invert ); return Py::None(); } Py::Object PythonExtensionBase::number_int() { missing_method( number_int ); return Py::None(); } Py::Object PythonExtensionBase::number_float() { missing_method( number_float ); return Py::None(); } Py::Object PythonExtensionBase::number_long() { missing_method( number_long ); return Py::None(); } Py::Object PythonExtensionBase::number_add( const Py::Object & ) { missing_method( number_add ); return Py::None(); } Py::Object PythonExtensionBase::number_subtract( const Py::Object & ) { missing_method( number_subtract ); return Py::None(); } Py::Object PythonExtensionBase::number_multiply( const Py::Object & ) { missing_method( number_multiply ); return Py::None(); } Py::Object PythonExtensionBase::number_remainder( const Py::Object & ) { missing_method( number_remainder ); return Py::None(); } Py::Object PythonExtensionBase::number_divmod( const Py::Object & ) { missing_method( number_divmod ); return Py::None(); } Py::Object PythonExtensionBase::number_lshift( const Py::Object & ) { missing_method( number_lshift ); return Py::None(); } Py::Object PythonExtensionBase::number_rshift( const Py::Object & ) { missing_method( number_rshift ); return Py::None(); } Py::Object PythonExtensionBase::number_and( const Py::Object & ) { missing_method( number_and ); return Py::None(); } Py::Object PythonExtensionBase::number_xor( const Py::Object & ) { missing_method( number_xor ); return Py::None(); } Py::Object PythonExtensionBase::number_or( const Py::Object & ) { missing_method( number_or ); return Py::None(); } Py::Object PythonExtensionBase::number_power( const Py::Object &, const Py::Object & ) { missing_method( number_power ); return Py::None(); } // Buffer int PythonExtensionBase::buffer_get( Py_buffer *buf, int flags ) { missing_method( buffer_get ); return -1; } int PythonExtensionBase::buffer_release( Py_buffer *buf ) { /* This method is optional and only required if the buffer's memory is dynamic. */ return 0; } //-------------------------------------------------------------------------------- // // Method call handlers for // PythonExtensionBase // ExtensionModuleBase // //-------------------------------------------------------------------------------- // Note: Python calls noargs as varargs buts args==NULL extern "C" PyObject *method_noargs_call_handler( PyObject *_self_and_name_tuple, PyObject * ) { try { Tuple self_and_name_tuple( _self_and_name_tuple ); PyObject *self_in_cobject = self_and_name_tuple[0].ptr(); void *self_as_void = PyCapsule_GetPointer( self_in_cobject, NULL ); if( self_as_void == NULL ) return NULL; ExtensionModuleBase *self = static_cast( self_as_void ); Object result( self->invoke_method_noargs( PyCapsule_GetPointer( self_and_name_tuple[1].ptr(), NULL ) ) ); return new_reference_to( result.ptr() ); } catch( Exception & ) { return 0; } } extern "C" PyObject *method_varargs_call_handler( PyObject *_self_and_name_tuple, PyObject *_args ) { try { Tuple self_and_name_tuple( _self_and_name_tuple ); PyObject *self_in_cobject = self_and_name_tuple[0].ptr(); void *self_as_void = PyCapsule_GetPointer( self_in_cobject, NULL ); if( self_as_void == NULL ) return NULL; ExtensionModuleBase *self = static_cast( self_as_void ); Tuple args( _args ); Object result ( self->invoke_method_varargs ( PyCapsule_GetPointer( self_and_name_tuple[1].ptr(), NULL ), args ) ); return new_reference_to( result.ptr() ); } catch( Exception & ) { return 0; } } extern "C" PyObject *method_keyword_call_handler( PyObject *_self_and_name_tuple, PyObject *_args, PyObject *_keywords ) { try { Tuple self_and_name_tuple( _self_and_name_tuple ); PyObject *self_in_cobject = self_and_name_tuple[0].ptr(); void *self_as_void = PyCapsule_GetPointer( self_in_cobject, NULL ); if( self_as_void == NULL ) return NULL; ExtensionModuleBase *self = static_cast( self_as_void ); Tuple args( _args ); if( _keywords == NULL ) { Dict keywords; // pass an empty dict Object result ( self->invoke_method_keyword ( PyCapsule_GetPointer( self_and_name_tuple[1].ptr(), NULL ), args, keywords ) ); return new_reference_to( result.ptr() ); } else { Dict keywords( _keywords ); // make dict Object result ( self->invoke_method_keyword ( PyCapsule_GetPointer( self_and_name_tuple[1].ptr(), NULL ), args, keywords ) ); return new_reference_to( result.ptr() ); } } catch( Exception & ) { return 0; } } //-------------------------------------------------------------------------------- // // ExtensionExceptionType // //-------------------------------------------------------------------------------- ExtensionExceptionType::ExtensionExceptionType() : Py::Object() { } void ExtensionExceptionType::init( ExtensionModuleBase &module, const std::string& name ) { std::string module_name( module.fullName() ); module_name += "."; module_name += name; set( PyErr_NewException( const_cast( module_name.c_str() ), NULL, NULL ), true ); } void ExtensionExceptionType::init( ExtensionModuleBase &module, const std::string& name, ExtensionExceptionType &parent ) { std::string module_name( module.fullName() ); module_name += "."; module_name += name; set( PyErr_NewException( const_cast( module_name.c_str() ), parent.ptr(), NULL ), true ); } ExtensionExceptionType::~ExtensionExceptionType() { } Exception::Exception( ExtensionExceptionType &exception, const std::string& reason ) { PyErr_SetString( exception.ptr(), reason.c_str() ); } Exception::Exception( ExtensionExceptionType &exception, Object &reason ) { PyErr_SetObject( exception.ptr(), reason.ptr() ); } Exception::Exception( PyObject *exception, Object &reason ) { PyErr_SetObject( exception, reason.ptr() ); } #if 1 //------------------------------------------------------------ // compare operators bool operator!=( const Long &a, const Long &b ) { return a.as_long() != b.as_long(); } bool operator!=( const Long &a, int b ) { return a.as_long() != b; } bool operator!=( const Long &a, long b ) { return a.as_long() != b; } bool operator!=( int a, const Long &b ) { return a != b.as_long(); } bool operator!=( long a, const Long &b ) { return a != b.as_long(); } //------------------------------ bool operator==( const Long &a, const Long &b ) { return a.as_long() == b.as_long(); } bool operator==( const Long &a, int b ) { return a.as_long() == b; } bool operator==( const Long &a, long b ) { return a.as_long() == b; } bool operator==( int a, const Long &b ) { return a == b.as_long(); } bool operator==( long a, const Long &b ) { return a == b.as_long(); } //------------------------------ bool operator>( const Long &a, const Long &b ) { return a.as_long() > b.as_long(); } bool operator>( const Long &a, int b ) { return a.as_long() > b; } bool operator>( const Long &a, long b ) { return a.as_long() > b; } bool operator>( int a, const Long &b ) { return a > b.as_long(); } bool operator>( long a, const Long &b ) { return a > b.as_long(); } //------------------------------ bool operator>=( const Long &a, const Long &b ) { return a.as_long() >= b.as_long(); } bool operator>=( const Long &a, int b ) { return a.as_long() >= b; } bool operator>=( const Long &a, long b ) { return a.as_long() >= b; } bool operator>=( int a, const Long &b ) { return a >= b.as_long(); } bool operator>=( long a, const Long &b ) { return a >= b.as_long(); } //------------------------------ bool operator<( const Long &a, const Long &b ) { return a.as_long() < b.as_long(); } bool operator<( const Long &a, int b ) { return a.as_long() < b; } bool operator<( const Long &a, long b ) { return a.as_long() < b; } bool operator<( int a, const Long &b ) { return a < b.as_long(); } bool operator<( long a, const Long &b ) { return a < b.as_long(); } //------------------------------ bool operator<=( const Long &a, const Long &b ) { return a.as_long() <= b.as_long(); } bool operator<=( int a, const Long &b ) { return a <= b.as_long(); } bool operator<=( long a, const Long &b ) { return a <= b.as_long(); } bool operator<=( const Long &a, int b ) { return a.as_long() <= b; } bool operator<=( const Long &a, long b ) { return a.as_long() <= b; } #ifdef HAVE_LONG_LONG //------------------------------ bool operator!=( const Long &a, PY_LONG_LONG b ) { return a.as_long_long() != b; } bool operator!=( PY_LONG_LONG a, const Long &b ) { return a != b.as_long_long(); } //------------------------------ bool operator==( const Long &a, PY_LONG_LONG b ) { return a.as_long_long() == b; } bool operator==( PY_LONG_LONG a, const Long &b ) { return a == b.as_long_long(); } //------------------------------ bool operator>( const Long &a, PY_LONG_LONG b ) { return a.as_long_long() > b; } bool operator>( PY_LONG_LONG a, const Long &b ) { return a > b.as_long_long(); } //------------------------------ bool operator>=( const Long &a, PY_LONG_LONG b ) { return a.as_long_long() >= b; } bool operator>=( PY_LONG_LONG a, const Long &b ) { return a >= b.as_long_long(); } //------------------------------ bool operator<( const Long &a, PY_LONG_LONG b ) { return a.as_long_long() < b; } bool operator<( PY_LONG_LONG a, const Long &b ) { return a < b.as_long_long(); } //------------------------------ bool operator<=( const Long &a, PY_LONG_LONG b ) { return a.as_long_long() <= b; } bool operator<=( PY_LONG_LONG a, const Long &b ) { return a <= b.as_long_long(); } #endif #endif //------------------------------------------------------------ // compare operators bool operator!=( const Float &a, const Float &b ) { return a.as_double() != b.as_double(); } bool operator!=( const Float &a, double b ) { return a.as_double() != b; } bool operator!=( double a, const Float &b ) { return a != b.as_double(); } //------------------------------ bool operator==( const Float &a, const Float &b ) { return a.as_double() == b.as_double(); } bool operator==( const Float &a, double b ) { return a.as_double() == b; } bool operator==( double a, const Float &b ) { return a == b.as_double(); } //------------------------------ bool operator>( const Float &a, const Float &b ) { return a.as_double() > b.as_double(); } bool operator>( const Float &a, double b ) { return a.as_double() > b; } bool operator>( double a, const Float &b ) { return a > b.as_double(); } //------------------------------ bool operator>=( const Float &a, const Float &b ) { return a.as_double() >= b.as_double(); } bool operator>=( const Float &a, double b ) { return a.as_double() >= b; } bool operator>=( double a, const Float &b ) { return a >= b.as_double(); } //------------------------------ bool operator<( const Float &a, const Float &b ) { return a.as_double() < b.as_double(); } bool operator<( const Float &a, double b ) { return a.as_double() < b; } bool operator<( double a, const Float &b ) { return a < b.as_double(); } //------------------------------ bool operator<=( const Float &a, const Float &b ) { return a.as_double() <= b.as_double(); } bool operator<=( double a, const Float &b ) { return a <= b.as_double(); } bool operator<=( const Float &a, double b ) { return a.as_double() <= b; } } // end of namespace Py pycxx-6.2.5/Src/Python3/cxxextensions.c000644 000771 000000 00000004473 11146616710 020345 0ustar00barrywheel000000 000000 /*---------------------------------------------------------------------------- // // Copyright (c) 1998 - 2007, The Regents of the University of California // Produced at the Lawrence Livermore National Laboratory // All rights reserved. // // This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The // full copyright notice is contained in the file COPYRIGHT located at the root // of the PyCXX distribution. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // - Redistributions of source code must retain the above copyright notice, // this list of conditions and the disclaimer below. // - Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the disclaimer (as noted below) in the // documentation and/or materials provided with the distribution. // - Neither the name of the UC/LLNL nor the names of its contributors may be // used to endorse or promote products derived from this software without // specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF // CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH // DAMAGE. // //---------------------------------------------------------------------------*/ #include "CXX/WrapPython.h" #ifdef __cplusplus extern "C" { #endif PyObject py_object_initializer = { _PyObject_EXTRA_INIT 1, NULL // type must be init'ed by user }; #ifdef __cplusplus } #endif pycxx-6.2.5/Src/Python3/cxxsupport.cxx000644 000771 000000 00000014362 11146616710 020240 0ustar00barrywheel000000 000000 //----------------------------------------------------------------------------- // // Copyright (c) 1998 - 2007, The Regents of the University of California // Produced at the Lawrence Livermore National Laboratory // All rights reserved. // // This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The // full copyright notice is contained in the file COPYRIGHT located at the root // of the PyCXX distribution. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // - Redistributions of source code must retain the above copyright notice, // this list of conditions and the disclaimer below. // - Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the disclaimer (as noted below) in the // documentation and/or materials provided with the distribution. // - Neither the name of the UC/LLNL nor the names of its contributors may be // used to endorse or promote products derived from this software without // specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF // CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH // DAMAGE. // //----------------------------------------------------------------------------- #include "CXX/Objects.hxx" namespace Py { Py_UNICODE unicode_null_string[1] = { 0 }; Type Object::type() const { return Type( PyObject_Type( p ), true ); } String Object::str() const { return String( PyObject_Str( p ), true ); } String Object::repr() const { return String( PyObject_Repr( p ), true ); } std::string Object::as_string() const { return static_cast( str() ); } List Object::dir() const { return List( PyObject_Dir( p ), true ); } bool Object::isType( const Type &t ) const { return type().ptr() == t.ptr(); } Char::operator String() const { return String( ptr() ); } String Bytes::decode( const char *encoding, const char *error ) { return String( PyUnicode_FromEncodedObject( ptr(), encoding, error ), true ); } // Object compares bool operator==( const Object &o1, const Object &o2 ) { int k = PyObject_RichCompareBool( *o1, *o2, Py_EQ ); if( PyErr_Occurred() ) throw Exception(); return k != 0; } bool operator!=( const Object &o1, const Object &o2 ) { int k = PyObject_RichCompareBool( *o1, *o2, Py_NE ); if( PyErr_Occurred() ) throw Exception(); return k != 0; } bool operator>=( const Object &o1, const Object &o2 ) { int k = PyObject_RichCompareBool( *o1, *o2, Py_GE ); if( PyErr_Occurred() ) throw Exception(); return k != 0; } bool operator<=( const Object &o1, const Object &o2 ) { int k = PyObject_RichCompareBool( *o1, *o2, Py_LE ); if( PyErr_Occurred() ) throw Exception(); return k != 0; } bool operator<( const Object &o1, const Object &o2 ) { int k = PyObject_RichCompareBool( *o1, *o2, Py_LT ); if( PyErr_Occurred() ) throw Exception(); return k != 0; } bool operator>( const Object &o1, const Object &o2 ) { int k = PyObject_RichCompareBool( *o1, *o2, Py_GT ); if( PyErr_Occurred() ) throw Exception(); return k != 0; } // iterator compares bool operator==( const Sequence::iterator &left, const Sequence::iterator &right ) { return left.eql( right ); } bool operator!=( const Sequence::iterator &left, const Sequence::iterator &right ) { return left.neq( right ); } bool operator<( const Sequence::iterator &left, const Sequence::iterator &right ) { return left.lss( right ); } bool operator>( const Sequence::iterator &left, const Sequence::iterator &right ) { return left.gtr( right ); } bool operator<=( const Sequence::iterator &left, const Sequence::iterator &right ) { return left.leq( right ); } bool operator>=( const Sequence::iterator &left, const Sequence::iterator &right ) { return left.geq( right ); } // const_iterator compares bool operator==( const Sequence::const_iterator &left, const Sequence::const_iterator &right ) { return left.eql( right ); } bool operator!=( const Sequence::const_iterator &left, const Sequence::const_iterator &right ) { return left.neq( right ); } bool operator<( const Sequence::const_iterator &left, const Sequence::const_iterator &right ) { return left.lss( right ); } bool operator>( const Sequence::const_iterator &left, const Sequence::const_iterator &right ) { return left.gtr( right ); } bool operator<=( const Sequence::const_iterator &left, const Sequence::const_iterator &right ) { return left.leq( right ); } bool operator>=( const Sequence::const_iterator &left, const Sequence::const_iterator &right ) { return left.geq( right ); } // For mappings: bool operator==( const Mapping::iterator &left, const Mapping::iterator &right ) { return left.eql( right ); } bool operator!=( const Mapping::iterator &left, const Mapping::iterator &right ) { return left.neq( right ); } // now for const_iterator bool operator==( const Mapping::const_iterator &left, const Mapping::const_iterator &right ) { return left.eql( right ); } bool operator!=( const Mapping::const_iterator &left, const Mapping::const_iterator &right ) { return left.neq( right ); } // TMM: 31May'01 - Added the #ifndef so I can exclude iostreams. #ifndef CXX_NO_IOSTREAMS // output std::ostream &operator<<( std::ostream &os, const Object &ob ) { return( os << static_cast( ob.str() ) ); } #endif } // Py pycxx-6.2.5/Src/Python2/cxx_extensions.cxx000644 000771 000000 00000141147 12160124333 021053 0ustar00barrywheel000000 000000 //----------------------------------------------------------------------------- // // Copyright (c) 1998 - 2007, The Regents of the University of California // Produced at the Lawrence Livermore National Laboratory // All rights reserved. // // This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The // full copyright notice is contained in the file COPYRIGHT located at the root // of the PyCXX distribution. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // - Redistributions of source code must retain the above copyright notice, // this list of conditions and the disclaimer below. // - Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the disclaimer (as noted below) in the // documentation and/or materials provided with the distribution. // - Neither the name of the UC/LLNL nor the names of its contributors may be // used to endorse or promote products derived from this software without // specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF // CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH // DAMAGE. // //----------------------------------------------------------------------------- #include "CXX/Extensions.hxx" #include "CXX/Exception.hxx" #include #ifdef PYCXX_DEBUG // // Functions useful when debugging PyCXX // void bpt( void ) { } void printRefCount( PyObject *obj ) { std::cout << "RefCount of 0x" << std::hex << reinterpret_cast< unsigned int >( obj ) << std::dec << " is " << Py_REFCNT( obj ) << std::endl; } #endif namespace Py { #ifdef PYCXX_PYTHON_2TO3 std::string String::as_std_string( const char *encoding, const char *error ) const { if( isUnicode() ) { Bytes encoded( encode( encoding, error ) ); return encoded.as_std_string(); } else { return std::string( PyString_AsString( ptr() ), static_cast( PyString_Size( ptr() ) ) ); } } Bytes String::encode( const char *encoding, const char *error ) const { if( isUnicode() ) { return Bytes( PyUnicode_AsEncodedString( ptr(), encoding, error ) ); } else { return Bytes( PyString_AsEncodedObject( ptr(), encoding, error ) ); } } #else std::string String::as_std_string( const char *encoding, const char *error ) const { if( isUnicode() ) { String encoded( encode( encoding, error ) ); return encoded.as_std_string(); } else { return std::string( PyString_AsString( ptr() ), static_cast( PyString_Size( ptr() ) ) ); } } #endif void Object::validate() { // release pointer if not the right type if( !accepts( p ) ) { #if defined( _CPPRTTI ) || defined( __GNUG__ ) std::string s( "PyCXX: Error creating object of type " ); s += (typeid( *this )).name(); if( p != NULL ) { String from_repr = repr(); s += " from "; s += from_repr.as_std_string( "utf-8" ); } else { s += " from (nil)"; } #endif release(); if( PyErr_Occurred() ) { // Error message already set throw Exception(); } // Better error message if RTTI available #if defined( _CPPRTTI ) || defined( __GNUG__ ) throw TypeError( s ); #else throw TypeError( "PyCXX: type error." ); #endif } } //================================================================================ // // Implementation of MethodTable // //================================================================================ PyMethodDef MethodTable::method( const char *method_name, PyCFunction f, int flags, const char *doc ) { PyMethodDef m; m.ml_name = const_cast( method_name ); m.ml_meth = f; m.ml_flags = flags; m.ml_doc = const_cast( doc ); return m; } MethodTable::MethodTable() { t.push_back( method( 0, 0, 0, 0 ) ); mt = NULL; } MethodTable::~MethodTable() { delete [] mt; } void MethodTable::add( const char *method_name, PyCFunction f, const char *doc, int flag ) { if( !mt ) { t.insert( t.end()-1, method( method_name, f, flag, doc ) ); } else { throw RuntimeError( "Too late to add a module method!" ); } } PyMethodDef *MethodTable::table() { if( !mt ) { Py_ssize_t t1size = t.size(); mt = new PyMethodDef[ t1size ]; int j = 0; for( std::vector::iterator i = t.begin(); i != t.end(); i++ ) { mt[ j++ ] = *i; } } return mt; } //================================================================================ // // Implementation of ExtensionModule // //================================================================================ ExtensionModuleBase::ExtensionModuleBase( const char *name ) : m_module_name( name ) , m_full_module_name( __Py_PackageContext() != NULL ? std::string( __Py_PackageContext() ) : m_module_name ) , m_method_table() {} ExtensionModuleBase::~ExtensionModuleBase() {} const std::string &ExtensionModuleBase::name() const { return m_module_name; } const std::string &ExtensionModuleBase::fullName() const { return m_full_module_name; } class ExtensionModuleBasePtr : public PythonExtension { public: ExtensionModuleBasePtr( ExtensionModuleBase *_module ) : module( _module ) {} virtual ~ExtensionModuleBasePtr() {} ExtensionModuleBase *module; }; void ExtensionModuleBase::initialize( const char *module_doc ) { PyObject *module_ptr = new ExtensionModuleBasePtr( this ); Py_InitModule4 ( const_cast( m_module_name.c_str() ), // name m_method_table.table(), // methods const_cast( module_doc ), // docs module_ptr, // pass to functions as "self" PYTHON_API_VERSION // API version ); } Py::Module ExtensionModuleBase::module( void ) const { return Module( m_full_module_name ); } Py::Dict ExtensionModuleBase::moduleDictionary( void ) const { return module().getDict(); } //================================================================================ // // Implementation of PythonType // //================================================================================ extern "C" { static void standard_dealloc( PyObject *p ); // // All the following functions redirect the call from Python // onto the matching virtual function in PythonExtensionBase // #if defined( PYCXX_PYTHON_2TO3 ) static int print_handler( PyObject *, FILE *, int ); #endif static PyObject *getattr_handler( PyObject *, char * ); static int setattr_handler( PyObject *, char *, PyObject * ); static PyObject *getattro_handler( PyObject *, PyObject * ); static int setattro_handler( PyObject *, PyObject *, PyObject * ); #if defined( PYCXX_PYTHON_2TO3 ) static int compare_handler( PyObject *, PyObject * ); #endif static PyObject *rich_compare_handler( PyObject *, PyObject *, int ); static PyObject *repr_handler( PyObject * ); static PyObject *str_handler( PyObject * ); static long hash_handler( PyObject * ); static PyObject *call_handler( PyObject *, PyObject *, PyObject * ); static PyObject *iter_handler( PyObject * ); static PyObject *iternext_handler( PyObject * ); // Sequence methods static Py_ssize_t sequence_length_handler( PyObject * ); static PyObject *sequence_concat_handler( PyObject *,PyObject * ); static PyObject *sequence_repeat_handler( PyObject *, Py_ssize_t ); static PyObject *sequence_item_handler( PyObject *, Py_ssize_t ); static PyObject *sequence_slice_handler( PyObject *, Py_ssize_t, Py_ssize_t ); static int sequence_ass_item_handler( PyObject *, Py_ssize_t, PyObject * ); static int sequence_ass_slice_handler( PyObject *, Py_ssize_t, Py_ssize_t, PyObject * ); // Mapping static Py_ssize_t mapping_length_handler( PyObject * ); static PyObject *mapping_subscript_handler( PyObject *, PyObject * ); static int mapping_ass_subscript_handler( PyObject *, PyObject *, PyObject * ); // Numeric methods static int number_nonzero_handler( PyObject * ); static PyObject *number_negative_handler( PyObject * ); static PyObject *number_positive_handler( PyObject * ); static PyObject *number_absolute_handler( PyObject * ); static PyObject *number_invert_handler( PyObject * ); static PyObject *number_int_handler( PyObject * ); static PyObject *number_float_handler( PyObject * ); static PyObject *number_long_handler( PyObject * ); static PyObject *number_oct_handler( PyObject * ); static PyObject *number_hex_handler( PyObject * ); static PyObject *number_add_handler( PyObject *, PyObject * ); static PyObject *number_subtract_handler( PyObject *, PyObject * ); static PyObject *number_multiply_handler( PyObject *, PyObject * ); static PyObject *number_divide_handler( PyObject *, PyObject * ); static PyObject *number_remainder_handler( PyObject *, PyObject * ); static PyObject *number_divmod_handler( PyObject *, PyObject * ); static PyObject *number_lshift_handler( PyObject *, PyObject * ); static PyObject *number_rshift_handler( PyObject *, PyObject * ); static PyObject *number_and_handler( PyObject *, PyObject * ); static PyObject *number_xor_handler( PyObject *, PyObject * ); static PyObject *number_or_handler( PyObject *, PyObject * ); static PyObject *number_power_handler( PyObject *, PyObject *, PyObject * ); // Buffer static Py_ssize_t buffer_getreadbuffer_handler( PyObject *, Py_ssize_t, void ** ); static Py_ssize_t buffer_getwritebuffer_handler( PyObject *, Py_ssize_t, void ** ); static Py_ssize_t buffer_getsegcount_handler( PyObject *, Py_ssize_t * ); } extern "C" void standard_dealloc( PyObject *p ) { PyMem_DEL( p ); } bool PythonType::readyType() { return PyType_Ready( table ) >= 0; } PythonType &PythonType::supportSequenceType() { if( !sequence_table ) { sequence_table = new PySequenceMethods; memset( sequence_table, 0, sizeof( PySequenceMethods ) ); // ensure new fields are 0 table->tp_as_sequence = sequence_table; sequence_table->sq_length = sequence_length_handler; sequence_table->sq_concat = sequence_concat_handler; sequence_table->sq_repeat = sequence_repeat_handler; sequence_table->sq_item = sequence_item_handler; sequence_table->sq_slice = sequence_slice_handler; sequence_table->sq_ass_item = sequence_ass_item_handler; // BAS setup seperately? sequence_table->sq_ass_slice = sequence_ass_slice_handler; // BAS setup seperately? } return *this; } PythonType &PythonType::supportMappingType() { if( !mapping_table ) { mapping_table = new PyMappingMethods; memset( mapping_table, 0, sizeof( PyMappingMethods ) ); // ensure new fields are 0 table->tp_as_mapping = mapping_table; mapping_table->mp_length = mapping_length_handler; mapping_table->mp_subscript = mapping_subscript_handler; mapping_table->mp_ass_subscript = mapping_ass_subscript_handler; // BAS setup seperately? } return *this; } PythonType &PythonType::supportNumberType() { if( !number_table ) { number_table = new PyNumberMethods; memset( number_table, 0, sizeof( PyNumberMethods ) ); // ensure new fields are 0 table->tp_as_number = number_table; number_table->nb_add = number_add_handler; number_table->nb_subtract = number_subtract_handler; number_table->nb_multiply = number_multiply_handler; number_table->nb_divide = number_divide_handler; number_table->nb_remainder = number_remainder_handler; number_table->nb_divmod = number_divmod_handler; number_table->nb_power = number_power_handler; number_table->nb_negative = number_negative_handler; number_table->nb_positive = number_positive_handler; number_table->nb_absolute = number_absolute_handler; number_table->nb_nonzero = number_nonzero_handler; number_table->nb_invert = number_invert_handler; number_table->nb_lshift = number_lshift_handler; number_table->nb_rshift = number_rshift_handler; number_table->nb_and = number_and_handler; number_table->nb_xor = number_xor_handler; number_table->nb_or = number_or_handler; number_table->nb_coerce = 0; number_table->nb_int = number_int_handler; number_table->nb_long = number_long_handler; number_table->nb_float = number_float_handler; number_table->nb_oct = number_oct_handler; number_table->nb_hex = number_hex_handler; } return *this; } PythonType &PythonType::supportBufferType() { if( !buffer_table ) { buffer_table = new PyBufferProcs; memset( buffer_table, 0, sizeof( PyBufferProcs ) ); // ensure new fields are 0 table->tp_as_buffer = buffer_table; buffer_table->bf_getreadbuffer = buffer_getreadbuffer_handler; buffer_table->bf_getwritebuffer = buffer_getwritebuffer_handler; buffer_table->bf_getsegcount = buffer_getsegcount_handler; } return *this; } // if you define one sequence method you must define // all of them except the assigns PythonType::PythonType( size_t basic_size, int itemsize, const char *default_name ) : table( new PyTypeObject ) , sequence_table( NULL ) , mapping_table( NULL ) , number_table( NULL ) , buffer_table( NULL ) { // PyTypeObject is defined in /Include/object.h memset( table, 0, sizeof( PyTypeObject ) ); // ensure new fields are 0 *reinterpret_cast( table ) = py_object_initializer; table->ob_type = _Type_Type(); table->ob_size = 0; table->tp_name = const_cast( default_name ); table->tp_basicsize = basic_size; table->tp_itemsize = itemsize; // Methods to implement standard operations table->tp_dealloc = (destructor)standard_dealloc; table->tp_print = 0; table->tp_getattr = 0; table->tp_setattr = 0; table->tp_compare = 0; table->tp_repr = 0; // Method suites for standard classes table->tp_as_number = 0; table->tp_as_sequence = 0; table->tp_as_mapping = 0; // More standard operations (here for binary compatibility) table->tp_hash = 0; table->tp_call = 0; table->tp_str = 0; table->tp_getattro = 0; table->tp_setattro = 0; // Functions to access object as input/output buffer table->tp_as_buffer = 0; // Flags to define presence of optional/expanded features table->tp_flags = Py_TPFLAGS_DEFAULT; // Documentation string table->tp_doc = 0; #if PY_MAJOR_VERSION > 2 || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION >= 0) table->tp_traverse = 0L; // delete references to contained objects table->tp_clear = 0L; #else table->tp_xxx5 = 0L; table->tp_xxx6 = 0L; #endif #if PY_MAJOR_VERSION > 2 || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION >= 1) // first defined in 2.1 table->tp_richcompare = 0L; // weak reference enabler table->tp_weaklistoffset = 0L; #else table->tp_xxx7 = 0L; table->tp_xxx8 = 0L; #endif #if PY_MAJOR_VERSION > 2 || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION >= 2) // first defined in 2.3 // Iterators table->tp_iter = 0L; table->tp_iternext = 0L; #endif #ifdef COUNT_ALLOCS table->tp_alloc = 0; table->tp_free = 0; table->tp_maxalloc = 0; table->tp_next = 0; #endif } PythonType::~PythonType() { delete table; delete sequence_table; delete mapping_table; delete number_table; delete buffer_table; } PyTypeObject *PythonType::type_object() const { return table; } PythonType &PythonType::name( const char *nam ) { table->tp_name = const_cast( nam ); return *this; } const char *PythonType::getName() const { return table->tp_name; } PythonType &PythonType::doc( const char *d ) { table->tp_doc = const_cast( d ); return *this; } const char *PythonType::getDoc() const { return table->tp_doc; } PythonType &PythonType::set_tp_dealloc( void (*tp_dealloc)( PyObject *self ) ) { table->tp_dealloc = tp_dealloc; return *this; } PythonType &PythonType::set_tp_init( int (*tp_init)( PyObject *self, PyObject *args, PyObject *kwds ) ) { table->tp_init = tp_init; return *this; } PythonType &PythonType::set_tp_new( PyObject *(*tp_new)( PyTypeObject *subtype, PyObject *args, PyObject *kwds ) ) { table->tp_new = tp_new; return *this; } PythonType &PythonType::set_methods( PyMethodDef *methods ) { table->tp_methods = methods; return *this; } PythonType &PythonType::supportClass() { table->tp_flags |= Py_TPFLAGS_BASETYPE; return *this; } PythonType &PythonType::dealloc( void( *f )( PyObject * )) { table->tp_dealloc = f; return *this; } #if defined( PYCXX_PYTHON_2TO3 ) PythonType &PythonType::supportPrint() { table->tp_print = print_handler; return *this; } #endif PythonType &PythonType::supportGetattr() { table->tp_getattr = getattr_handler; return *this; } PythonType &PythonType::supportSetattr() { table->tp_setattr = setattr_handler; return *this; } PythonType &PythonType::supportGetattro() { table->tp_getattro = getattro_handler; return *this; } PythonType &PythonType::supportSetattro() { table->tp_setattro = setattro_handler; return *this; } #if defined( PYCXX_PYTHON_2TO3 ) PythonType &PythonType::supportCompare() { table->tp_compare = compare_handler; return *this; } #endif #if PY_MAJOR_VERSION > 2 || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION >= 1) PythonType &PythonType::supportRichCompare() { table->tp_richcompare = rich_compare_handler; return *this; } #endif PythonType &PythonType::supportRepr() { table->tp_repr = repr_handler; return *this; } PythonType &PythonType::supportStr() { table->tp_str = str_handler; return *this; } PythonType &PythonType::supportHash() { table->tp_hash = hash_handler; return *this; } PythonType &PythonType::supportCall() { table->tp_call = call_handler; return *this; } PythonType &PythonType::supportIter() { table->tp_iter = iter_handler; table->tp_iternext = iternext_handler; return *this; } //-------------------------------------------------------------------------------- // // Handlers // //-------------------------------------------------------------------------------- PythonExtensionBase *getPythonExtensionBase( PyObject *self ) { if( self->ob_type->tp_flags&Py_TPFLAGS_BASETYPE ) { PythonClassInstance *instance = reinterpret_cast( self ); return instance->m_pycxx_object; } else { return static_cast( self ); } } #if defined( PYCXX_PYTHON_2TO3 ) extern "C" int print_handler( PyObject *self, FILE *fp, int flags ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return p->print( fp, flags ); } catch( Py::Exception &) { return -1; // indicate error } } #endif extern "C" PyObject *getattr_handler( PyObject *self, char *name ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return new_reference_to( p->getattr( name ) ); } catch( Py::Exception &) { return NULL; // indicate error } } extern "C" int setattr_handler( PyObject *self, char *name, PyObject *value ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return p->setattr( name, Py::Object( value ) ); } catch( Py::Exception &) { return -1; // indicate error } } extern "C" PyObject *getattro_handler( PyObject *self, PyObject *name ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return new_reference_to( p->getattro( Py::String( name ) ) ); } catch( Py::Exception &) { return NULL; // indicate error } } extern "C" int setattro_handler( PyObject *self, PyObject *name, PyObject *value ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return p->setattro( Py::String( name ), Py::Object( value ) ); } catch( Py::Exception &) { return -1; // indicate error } } #if defined( PYCXX_PYTHON_2TO3 ) extern "C" int compare_handler( PyObject *self, PyObject *other ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return p->compare( Py::Object( other ) ); } catch( Py::Exception &) { return -1; // indicate error } } #endif #if PY_MAJOR_VERSION > 2 || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION >= 1) extern "C" PyObject *rich_compare_handler( PyObject *self, PyObject *other, int op ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return new_reference_to( p->rich_compare( Py::Object( other ), op ) ); } catch( Py::Exception &) { return NULL; // indicate error } } #endif extern "C" PyObject *repr_handler( PyObject *self ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return new_reference_to( p->repr() ); } catch( Py::Exception &) { return NULL; // indicate error } } extern "C" PyObject *str_handler( PyObject *self ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return new_reference_to( p->str() ); } catch( Py::Exception &) { return NULL; // indicate error } } extern "C" long hash_handler( PyObject *self ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return p->hash(); } catch( Py::Exception &) { return -1; // indicate error } } extern "C" PyObject *call_handler( PyObject *self, PyObject *args, PyObject *kw ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); if( kw != NULL ) return new_reference_to( p->call( Py::Object( args ), Py::Object( kw ) ) ); else return new_reference_to( p->call( Py::Object( args ), Py::Object() ) ); } catch( Py::Exception &) { return NULL; // indicate error } } extern "C" PyObject *iter_handler( PyObject *self ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return new_reference_to( p->iter() ); } catch( Py::Exception &) { return NULL; // indicate error } } extern "C" PyObject *iternext_handler( PyObject *self ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return p->iternext(); // might be a NULL ptr on end of iteration } catch( Py::Exception &) { return NULL; // indicate error } } // Sequence methods extern "C" Py_ssize_t sequence_length_handler( PyObject *self ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return p->sequence_length(); } catch( Py::Exception &) { return -1; // indicate error } } extern "C" PyObject *sequence_concat_handler( PyObject *self, PyObject *other ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return new_reference_to( p->sequence_concat( Py::Object( other ) ) ); } catch( Py::Exception &) { return NULL; // indicate error } } extern "C" PyObject *sequence_repeat_handler( PyObject *self, Py_ssize_t count ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return new_reference_to( p->sequence_repeat( count ) ); } catch( Py::Exception &) { return NULL; // indicate error } } extern "C" PyObject *sequence_item_handler( PyObject *self, Py_ssize_t index ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return new_reference_to( p->sequence_item( index ) ); } catch( Py::Exception &) { return NULL; // indicate error } } extern "C" PyObject *sequence_slice_handler( PyObject *self, Py_ssize_t first, Py_ssize_t last ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return new_reference_to( p->sequence_slice( first, last ) ); } catch( Py::Exception &) { return NULL; // indicate error } } extern "C" int sequence_ass_item_handler( PyObject *self, Py_ssize_t index, PyObject *value ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return p->sequence_ass_item( index, Py::Object( value ) ); } catch( Py::Exception &) { return -1; // indicate error } } extern "C" int sequence_ass_slice_handler( PyObject *self, Py_ssize_t first, Py_ssize_t last, PyObject *value ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return p->sequence_ass_slice( first, last, Py::Object( value ) ); } catch( Py::Exception &) { return -1; // indicate error } } // Mapping extern "C" Py_ssize_t mapping_length_handler( PyObject *self ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return p->mapping_length(); } catch( Py::Exception &) { return -1; // indicate error } } extern "C" PyObject *mapping_subscript_handler( PyObject *self, PyObject *key ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return new_reference_to( p->mapping_subscript( Py::Object( key ) ) ); } catch( Py::Exception &) { return NULL; // indicate error } } extern "C" int mapping_ass_subscript_handler( PyObject *self, PyObject *key, PyObject *value ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return p->mapping_ass_subscript( Py::Object( key ), Py::Object( value ) ); } catch( Py::Exception &) { return -1; // indicate error } } // Number extern "C" int number_nonzero_handler( PyObject *self ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return p->number_nonzero(); } catch( Py::Exception &) { return -1; // indicate error } } extern "C" PyObject *number_negative_handler( PyObject *self ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return new_reference_to( p->number_negative() ); } catch( Py::Exception &) { return NULL; // indicate error } } extern "C" PyObject *number_positive_handler( PyObject *self ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return new_reference_to( p->number_positive() ); } catch( Py::Exception &) { return NULL; // indicate error } } extern "C" PyObject *number_absolute_handler( PyObject *self ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return new_reference_to( p->number_absolute() ); } catch( Py::Exception &) { return NULL; // indicate error } } extern "C" PyObject *number_invert_handler( PyObject *self ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return new_reference_to( p->number_invert() ); } catch( Py::Exception &) { return NULL; // indicate error } } extern "C" PyObject *number_int_handler( PyObject *self ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return new_reference_to( p->number_int() ); } catch( Py::Exception &) { return NULL; // indicate error } } extern "C" PyObject *number_float_handler( PyObject *self ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return new_reference_to( p->number_float() ); } catch( Py::Exception &) { return NULL; // indicate error } } extern "C" PyObject *number_long_handler( PyObject *self ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return new_reference_to( p->number_long() ); } catch( Py::Exception &) { return NULL; // indicate error } } extern "C" PyObject *number_oct_handler( PyObject *self ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return new_reference_to( p->number_oct() ); } catch( Py::Exception &) { return NULL; // indicate error } } extern "C" PyObject *number_hex_handler( PyObject *self ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return new_reference_to( p->number_hex() ); } catch( Py::Exception &) { return NULL; // indicate error } } extern "C" PyObject *number_add_handler( PyObject *self, PyObject *other ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return new_reference_to( p->number_add( Py::Object( other ) ) ); } catch( Py::Exception &) { return NULL; // indicate error } } extern "C" PyObject *number_subtract_handler( PyObject *self, PyObject *other ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return new_reference_to( p->number_subtract( Py::Object( other ) ) ); } catch( Py::Exception &) { return NULL; // indicate error } } extern "C" PyObject *number_multiply_handler( PyObject *self, PyObject *other ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return new_reference_to( p->number_multiply( Py::Object( other ) ) ); } catch( Py::Exception &) { return NULL; // indicate error } } extern "C" PyObject *number_divide_handler( PyObject *self, PyObject *other ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return new_reference_to( p->number_divide( Py::Object( other ) ) ); } catch( Py::Exception &) { return NULL; // indicate error } } extern "C" PyObject *number_remainder_handler( PyObject *self, PyObject *other ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return new_reference_to( p->number_remainder( Py::Object( other ) ) ); } catch( Py::Exception &) { return NULL; // indicate error } } extern "C" PyObject *number_divmod_handler( PyObject *self, PyObject *other ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return new_reference_to( p->number_divmod( Py::Object( other ) ) ); } catch( Py::Exception &) { return NULL; // indicate error } } extern "C" PyObject *number_lshift_handler( PyObject *self, PyObject *other ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return new_reference_to( p->number_lshift( Py::Object( other ) ) ); } catch( Py::Exception &) { return NULL; // indicate error } } extern "C" PyObject *number_rshift_handler( PyObject *self, PyObject *other ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return new_reference_to( p->number_rshift( Py::Object( other ) ) ); } catch( Py::Exception &) { return NULL; // indicate error } } extern "C" PyObject *number_and_handler( PyObject *self, PyObject *other ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return new_reference_to( p->number_and( Py::Object( other ) ) ); } catch( Py::Exception &) { return NULL; // indicate error } } extern "C" PyObject *number_xor_handler( PyObject *self, PyObject *other ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return new_reference_to( p->number_xor( Py::Object( other ) ) ); } catch( Py::Exception &) { return NULL; // indicate error } } extern "C" PyObject *number_or_handler( PyObject *self, PyObject *other ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return new_reference_to( p->number_or( Py::Object( other ) ) ); } catch( Py::Exception &) { return NULL; // indicate error } } extern "C" PyObject *number_power_handler( PyObject *self, PyObject *x1, PyObject *x2 ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return new_reference_to( p->number_power( Py::Object( x1 ), Py::Object( x2 ) ) ); } catch( Py::Exception &) { return NULL; // indicate error } } // Buffer extern "C" Py_ssize_t buffer_getreadbuffer_handler( PyObject *self, Py_ssize_t index, void **pp ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return p->buffer_getreadbuffer( index, pp ); } catch( Py::Exception &) { return -1; // indicate error } } extern "C" Py_ssize_t buffer_getwritebuffer_handler( PyObject *self, Py_ssize_t index, void **pp ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return p->buffer_getwritebuffer( index, pp ); } catch( Py::Exception &) { return -1; // indicate error } } extern "C" Py_ssize_t buffer_getsegcount_handler( PyObject *self, Py_ssize_t *count ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return p->buffer_getsegcount( count ); } catch( Py::Exception &) { return -1; // indicate error } } //================================================================================ // // Implementation of PythonExtensionBase // //================================================================================ #define missing_method( method ) \ throw RuntimeError( "Extension object missing implement of " #method ); PythonExtensionBase::PythonExtensionBase() { ob_refcnt = 0; } PythonExtensionBase::~PythonExtensionBase() { assert( ob_refcnt == 0 ); } Py::Object PythonExtensionBase::callOnSelf( const std::string &fn_name ) { Py::TupleN args; return self().callMemberFunction( fn_name, args ); } Py::Object PythonExtensionBase::callOnSelf( const std::string &fn_name, const Py::Object &arg1 ) { Py::TupleN args( arg1 ); return self().callMemberFunction( fn_name, args ); } Py::Object PythonExtensionBase::callOnSelf( const std::string &fn_name, const Py::Object &arg1, const Py::Object &arg2 ) { Py::TupleN args( arg1, arg2 ); return self().callMemberFunction( fn_name, args ); } Py::Object PythonExtensionBase::callOnSelf( const std::string &fn_name, const Py::Object &arg1, const Py::Object &arg2, const Py::Object &arg3 ) { Py::TupleN args( arg1, arg2, arg3 ); return self().callMemberFunction( fn_name, args ); } Py::Object PythonExtensionBase::callOnSelf( const std::string &fn_name, const Py::Object &arg1, const Py::Object &arg2, const Py::Object &arg3, const Py::Object &arg4 ) { Py::TupleN args( arg1, arg2, arg3, arg4 ); return self().callMemberFunction( fn_name, args ); } Py::Object PythonExtensionBase::callOnSelf( const std::string &fn_name, const Py::Object &arg1, const Py::Object &arg2, const Py::Object &arg3, const Py::Object &arg4, const Py::Object &arg5 ) { Py::TupleN args( arg1, arg2, arg3, arg4, arg5 ); return self().callMemberFunction( fn_name, args ); } Py::Object PythonExtensionBase::callOnSelf( const std::string &fn_name, const Py::Object &arg1, const Py::Object &arg2, const Py::Object &arg3, const Py::Object &arg4, const Py::Object &arg5, const Py::Object &arg6 ) { Py::TupleN args( arg1, arg2, arg3, arg4, arg5, arg6 ); return self().callMemberFunction( fn_name, args ); } Py::Object PythonExtensionBase::callOnSelf( const std::string &fn_name, const Py::Object &arg1, const Py::Object &arg2, const Py::Object &arg3, const Py::Object &arg4, const Py::Object &arg5, const Py::Object &arg6, const Py::Object &arg7 ) { Py::TupleN args( arg1, arg2, arg3, arg4, arg5, arg6, arg7 ); return self().callMemberFunction( fn_name, args ); } Py::Object PythonExtensionBase::callOnSelf( const std::string &fn_name, const Py::Object &arg1, const Py::Object &arg2, const Py::Object &arg3, const Py::Object &arg4, const Py::Object &arg5, const Py::Object &arg6, const Py::Object &arg7, const Py::Object &arg8 ) { Py::TupleN args( arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8 ); return self().callMemberFunction( fn_name, args ); } Py::Object PythonExtensionBase::callOnSelf( const std::string &fn_name, const Py::Object &arg1, const Py::Object &arg2, const Py::Object &arg3, const Py::Object &arg4, const Py::Object &arg5, const Py::Object &arg6, const Py::Object &arg7, const Py::Object &arg8, const Py::Object &arg9 ) { Py::TupleN args( arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9 ); return self().callMemberFunction( fn_name, args ); } void PythonExtensionBase::reinit( Tuple &args, Dict &kwds ) { throw RuntimeError( "Must not call __init__ twice on this class" ); } Py::Object PythonExtensionBase::genericGetAttro( const Py::String &name ) { return asObject( PyObject_GenericGetAttr( selfPtr(), name.ptr() ) ); } int PythonExtensionBase::genericSetAttro( const Py::String &name, const Py::Object &value ) { return PyObject_GenericSetAttr( selfPtr(), name.ptr(), value.ptr() ); } int PythonExtensionBase::print( FILE *, int ) { missing_method( print ); return -1; } Py::Object PythonExtensionBase::getattr( const char * ) { missing_method( getattr ); return Py::None(); } int PythonExtensionBase::setattr( const char *, const Py::Object &) { missing_method( setattr ); return -1; } Py::Object PythonExtensionBase::getattro( const Py::String &name ) { return genericGetAttro( name ); } int PythonExtensionBase::setattro( const Py::String &name, const Py::Object &value ) { return genericSetAttro( name, value ); } int PythonExtensionBase::compare( const Py::Object &) { missing_method( compare ); return -1; } #if PY_MAJOR_VERSION > 2 || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION >= 1) Py::Object PythonExtensionBase::rich_compare( const Py::Object &, int op ) { missing_method( rich_compare ); return Py::None(); } #endif Py::Object PythonExtensionBase::repr() { missing_method( repr ); return Py::None(); } Py::Object PythonExtensionBase::str() { missing_method( str ); return Py::None(); } long PythonExtensionBase::hash() { missing_method( hash ); return -1; } Py::Object PythonExtensionBase::call( const Py::Object &, const Py::Object &) { missing_method( call ); return Py::None(); } Py::Object PythonExtensionBase::iter() { missing_method( iter ); return Py::None(); } PyObject *PythonExtensionBase::iternext() { missing_method( iternext ); return NULL; } // Sequence methods int PythonExtensionBase::sequence_length() { missing_method( sequence_length ); return -1; } Py::Object PythonExtensionBase::sequence_concat( const Py::Object &) { missing_method( sequence_concat ); return Py::None(); } Py::Object PythonExtensionBase::sequence_repeat( Py_ssize_t ) { missing_method( sequence_repeat ); return Py::None(); } Py::Object PythonExtensionBase::sequence_item( Py_ssize_t ) { missing_method( sequence_item ); return Py::None(); } Py::Object PythonExtensionBase::sequence_slice( Py_ssize_t, Py_ssize_t ) { missing_method( sequence_slice ); return Py::None(); } int PythonExtensionBase::sequence_ass_item( Py_ssize_t, const Py::Object &) { missing_method( sequence_ass_item ); return -1; } int PythonExtensionBase::sequence_ass_slice( Py_ssize_t, Py_ssize_t, const Py::Object &) { missing_method( sequence_ass_slice ); return -1; } // Mapping int PythonExtensionBase::mapping_length() { missing_method( mapping_length ); return -1; } Py::Object PythonExtensionBase::mapping_subscript( const Py::Object &) { missing_method( mapping_subscript ); return Py::None(); } int PythonExtensionBase::mapping_ass_subscript( const Py::Object &, const Py::Object &) { missing_method( mapping_ass_subscript ); return -1; } // Number int PythonExtensionBase::number_nonzero() { missing_method( number_nonzero ); return -1; } Py::Object PythonExtensionBase::number_negative() { missing_method( number_negative ); return Py::None(); } Py::Object PythonExtensionBase::number_positive() { missing_method( number_positive ); return Py::None(); } Py::Object PythonExtensionBase::number_absolute() { missing_method( number_absolute ); return Py::None(); } Py::Object PythonExtensionBase::number_invert() { missing_method( number_invert ); return Py::None(); } Py::Object PythonExtensionBase::number_int() { missing_method( number_int ); return Py::None(); } Py::Object PythonExtensionBase::number_float() { missing_method( number_float ); return Py::None(); } Py::Object PythonExtensionBase::number_long() { missing_method( number_long ); return Py::None(); } Py::Object PythonExtensionBase::number_oct() { missing_method( number_oct ); return Py::None(); } Py::Object PythonExtensionBase::number_hex() { missing_method( number_hex ); return Py::None(); } Py::Object PythonExtensionBase::number_add( const Py::Object &) { missing_method( number_add ); return Py::None(); } Py::Object PythonExtensionBase::number_subtract( const Py::Object &) { missing_method( number_subtract ); return Py::None(); } Py::Object PythonExtensionBase::number_multiply( const Py::Object &) { missing_method( number_multiply ); return Py::None(); } Py::Object PythonExtensionBase::number_divide( const Py::Object &) { missing_method( number_divide ); return Py::None(); } Py::Object PythonExtensionBase::number_remainder( const Py::Object &) { missing_method( number_remainder ); return Py::None(); } Py::Object PythonExtensionBase::number_divmod( const Py::Object &) { missing_method( number_divmod ); return Py::None(); } Py::Object PythonExtensionBase::number_lshift( const Py::Object &) { missing_method( number_lshift ); return Py::None(); } Py::Object PythonExtensionBase::number_rshift( const Py::Object &) { missing_method( number_rshift ); return Py::None(); } Py::Object PythonExtensionBase::number_and( const Py::Object &) { missing_method( number_and ); return Py::None(); } Py::Object PythonExtensionBase::number_xor( const Py::Object &) { missing_method( number_xor ); return Py::None(); } Py::Object PythonExtensionBase::number_or( const Py::Object &) { missing_method( number_or ); return Py::None(); } Py::Object PythonExtensionBase::number_power( const Py::Object &, const Py::Object &) { missing_method( number_power ); return Py::None(); } // Buffer Py_ssize_t PythonExtensionBase::buffer_getreadbuffer( Py_ssize_t, void** ) { missing_method( buffer_getreadbuffer ); return -1; } Py_ssize_t PythonExtensionBase::buffer_getwritebuffer( Py_ssize_t, void** ) { missing_method( buffer_getwritebuffer ); return -1; } Py_ssize_t PythonExtensionBase::buffer_getsegcount( Py_ssize_t* ) { missing_method( buffer_getsegcount ); return -1; } //-------------------------------------------------------------------------------- // // Method call handlers for // PythonExtensionBase // ExtensionModuleBase // //-------------------------------------------------------------------------------- extern "C" PyObject *method_keyword_call_handler( PyObject *_self_and_name_tuple, PyObject *_args, PyObject *_keywords ) { try { Tuple self_and_name_tuple( _self_and_name_tuple ); PyObject *self_in_cobject = self_and_name_tuple[0].ptr(); void *self_as_void = PyCObject_AsVoidPtr( self_in_cobject ); if( self_as_void == NULL ) return NULL; ExtensionModuleBase *self = static_cast( self_as_void ); Tuple args( _args ); if( _keywords == NULL ) { Dict keywords; // pass an empty dict Object result ( self->invoke_method_keyword ( PyCObject_AsVoidPtr( self_and_name_tuple[1].ptr() ), args, keywords ) ); return new_reference_to( result.ptr() ); } else { Dict keywords( _keywords ); // make dict Object result ( self->invoke_method_keyword ( PyCObject_AsVoidPtr( self_and_name_tuple[1].ptr() ), args, keywords ) ); return new_reference_to( result.ptr() ); } } catch( Exception & ) { return 0; } } extern "C" PyObject *method_varargs_call_handler( PyObject *_self_and_name_tuple, PyObject *_args ) { try { Tuple self_and_name_tuple( _self_and_name_tuple ); PyObject *self_in_cobject = self_and_name_tuple[0].ptr(); void *self_as_void = PyCObject_AsVoidPtr( self_in_cobject ); if( self_as_void == NULL ) return NULL; ExtensionModuleBase *self = static_cast( self_as_void ); Tuple args( _args ); Object result ( self->invoke_method_varargs ( PyCObject_AsVoidPtr( self_and_name_tuple[1].ptr() ), args ) ); return new_reference_to( result.ptr() ); } catch( Exception & ) { return 0; } } extern "C" void do_not_dealloc( void * ) {} //-------------------------------------------------------------------------------- // // ExtensionExceptionType // //-------------------------------------------------------------------------------- ExtensionExceptionType::ExtensionExceptionType() : Py::Object() { } void ExtensionExceptionType::init( ExtensionModuleBase &module, const std::string& name ) { std::string module_name( module.fullName() ); module_name += "."; module_name += name; set( PyErr_NewException( const_cast( module_name.c_str() ), NULL, NULL ), true ); } void ExtensionExceptionType::init( ExtensionModuleBase &module, const std::string& name, ExtensionExceptionType &parent) { std::string module_name( module.fullName() ); module_name += "."; module_name += name; set( PyErr_NewException( const_cast( module_name.c_str() ), parent.ptr(), NULL ), true ); } ExtensionExceptionType::~ExtensionExceptionType() { } Exception::Exception( ExtensionExceptionType &exception, const std::string& reason ) { PyErr_SetString( exception.ptr(), reason.c_str() ); } Exception::Exception( ExtensionExceptionType &exception, Object &reason ) { PyErr_SetObject( exception.ptr(), reason.ptr() ); } Exception::Exception( PyObject *exception, Object &reason ) { PyErr_SetObject( exception, reason.ptr() ); } } // end of namespace Py pycxx-6.2.5/Src/Python2/cxxextensions.c000644 000771 000000 00000004371 11146616710 020341 0ustar00barrywheel000000 000000 /*---------------------------------------------------------------------------- // // Copyright (c) 1998 - 2007, The Regents of the University of California // Produced at the Lawrence Livermore National Laboratory // All rights reserved. // // This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The // full copyright notice is contained in the file COPYRIGHT located at the root // of the PyCXX distribution. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // - Redistributions of source code must retain the above copyright notice, // this list of conditions and the disclaimer below. // - Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the disclaimer (as noted below) in the // documentation and/or materials provided with the distribution. // - Neither the name of the UC/LLNL nor the names of its contributors may be // used to endorse or promote products derived from this software without // specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF // CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH // DAMAGE. // //---------------------------------------------------------------------------*/ #include "CXX/WrapPython.h" #ifdef __cplusplus extern "C" { #endif PyObject py_object_initializer = {PyObject_HEAD_INIT(0)}; #ifdef __cplusplus } #endif pycxx-6.2.5/Src/Python2/cxxsupport.cxx000644 000771 000000 00000012122 11146616710 020227 0ustar00barrywheel000000 000000 //----------------------------------------------------------------------------- // // Copyright (c) 1998 - 2007, The Regents of the University of California // Produced at the Lawrence Livermore National Laboratory // All rights reserved. // // This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The // full copyright notice is contained in the file COPYRIGHT located at the root // of the PyCXX distribution. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // - Redistributions of source code must retain the above copyright notice, // this list of conditions and the disclaimer below. // - Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the disclaimer (as noted below) in the // documentation and/or materials provided with the distribution. // - Neither the name of the UC/LLNL nor the names of its contributors may be // used to endorse or promote products derived from this software without // specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF // CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH // DAMAGE. // //----------------------------------------------------------------------------- #include "CXX/Objects.hxx" namespace Py { Py_UNICODE unicode_null_string[1] = { 0 }; Type Object::type () const { return Type (PyObject_Type (p), true); } String Object::str () const { return String (PyObject_Str (p), true); } String Object::repr () const { return String (PyObject_Repr (p), true); } std::string Object::as_string() const { return static_cast(str()); } List Object::dir () const { return List (PyObject_Dir (p), true); } bool Object::isType (const Type& t) const { return type ().ptr() == t.ptr(); } Char::operator String() const { return String(ptr()); } // TMM: non-member operaters for iterators - see above // I've also made a bug fix in respect to the cxx code // (dereffed the left.seq and right.seq comparison) bool operator==(const Sequence::iterator& left, const Sequence::iterator& right) { return left.eql( right ); } bool operator!=(const Sequence::iterator& left, const Sequence::iterator& right) { return left.neq( right ); } bool operator< (const Sequence::iterator& left, const Sequence::iterator& right) { return left.lss( right ); } bool operator> (const Sequence::iterator& left, const Sequence::iterator& right) { return left.gtr( right ); } bool operator<=(const Sequence::iterator& left, const Sequence::iterator& right) { return left.leq( right ); } bool operator>=(const Sequence::iterator& left, const Sequence::iterator& right) { return left.geq( right ); } // now for const_iterator bool operator==(const Sequence::const_iterator& left, const Sequence::const_iterator& right) { return left.eql( right ); } bool operator!=(const Sequence::const_iterator& left, const Sequence::const_iterator& right) { return left.neq( right ); } bool operator< (const Sequence::const_iterator& left, const Sequence::const_iterator& right) { return left.lss( right ); } bool operator> (const Sequence::const_iterator& left, const Sequence::const_iterator& right) { return left.gtr( right ); } bool operator<=(const Sequence::const_iterator& left, const Sequence::const_iterator& right) { return left.leq( right ); } bool operator>=(const Sequence::const_iterator& left, const Sequence::const_iterator& right) { return left.geq( right ); } // For mappings: bool operator==(const Mapping::iterator& left, const Mapping::iterator& right) { return left.eql( right ); } bool operator!=(const Mapping::iterator& left, const Mapping::iterator& right) { return left.neq( right ); } // now for const_iterator bool operator==(const Mapping::const_iterator& left, const Mapping::const_iterator& right) { return left.eql( right ); } bool operator!=(const Mapping::const_iterator& left, const Mapping::const_iterator& right) { return left.neq( right ); } // TMM: 31May'01 - Added the #ifndef so I can exclude iostreams. #ifndef CXX_NO_IOSTREAMS // output std::ostream& operator<< (std::ostream& os, const Object& ob) { return (os << static_cast(ob.str())); } #endif } // Py pycxx-6.2.5/SourceForge/deploy.sh000755 000771 000000 00000000774 11230647177 017247 0ustar00barrywheel000000 000000 #!/bin/sh scp index.html barry-scott,cxx@web.sourceforge.net:/home/groups/c/cx/cxx/htdocs/ scp ../README.html barry-scott,cxx@web.sourceforge.net:/home/groups/c/cx/cxx/htdocs/ scp ../Doc/Python2/PyCXX.html barry-scott,cxx@web.sourceforge.net:/home/groups/c/cx/cxx/htdocs/PyCXX-Python2.html scp ../Doc/Python3/style.css barry-scott,cxx@web.sourceforge.net:/home/groups/c/cx/cxx/htdocs/style.css scp ../Doc/Python3/PyCXX.html barry-scott,cxx@web.sourceforge.net:/home/groups/c/cx/cxx/htdocs/PyCXX-Python3.html pycxx-6.2.5/SourceForge/index.html000755 000771 000000 00000014655 12204157547 017416 0ustar00barrywheel000000 000000 PyCXX: Write Python Extensions in C++
PyCXX: Write Python Extensions in C++

Barry Scott, barry@barrys-emacs.org

The CXX Project Page at SourceForge Home gives you access to the releases, the Subversion repository, and more.

PyCXX is designed to make it easier to extend Python with C++

CXX/Objects is a set of C++ facilities to make it easier to write Python extensions. The chief way in which PyCXX makes it easier to write Python extensions is that it greatly increases the probability that your program will not make a reference-counting error and will not have to continually check error returns from the Python C API. CXX/Objects integrates Python with C++ in these ways:

  • C++ exception handling is relied on to detect errors and clean up. In a complicated function this is often a tremendous problem when writing in C. With PyCXX, we let the compiler keep track of what objects need to be dereferenced when an error occurs.
  • The Standard Template Library (STL) and its many algorithms plug and play with Python containers such as lists and tuples.
  • The optional CXX/Extensions facility allows you to replace the clumsy C tables with objects and method calls that define your modules and extension objects.

PyCXX documentation is split into Python 3 and Python 2 versions. The Python 3 documentation is the most accurate.

Latest PyCXX README file.


Version 6.2.5 (18-Aug-2013)

Fix build issue with GCC 4.2.1 on FreeBSD and Mac OS X (stop python defining isspace as a macro).

Remove support for python 3.1 (API's are unstable).

Add Python 3.3 support.

Patch frm Michael Droettboom to fix compilation issues.

Patch frm Michael Droettboom to add buffer interface for python3.

Version 6.2.4 (3-Mar-2012)

Fix memory leak in string encode and decode functions

Fix indirect python loading on windows - Bool_type was missing

Version 6.2.3 (11-mar-2011)

Fix memory leak in string encode and decode functions

Fix indirect python loading on windows - Bool_type was missing


Version 6.2.2 (26-Dec-2010)

Fix problem compiling against Python 3.1.3


Version 6.2.1 (15-Aug-2010)

Add support for NotImplementedError

Remove String() and Byte() c'tors that are not allowed by ISO C++ and where ambigous


Version 6.2.0 (9-May-2010)

Fix problems with new style classes.

Replace all example makefile and project files with setup_makefile.py script.

Add APIs to make calling python functions easier. See TupleN(), callOnSelf(), self()


Version 6.1.1 (26-Sep-2009)

Supports Python 3 starting at Python 3.1 and Python 2

Code clean up to fix compiler warnings reported by gcc 4.2.1 on Mac OS X when building for Python 3.


Version 6.1.0 (19-Jul-2009)

Supports Python 3 and Python 2

This release replaces 5.5.0 and 6.0.0

Speed of method calling has been improved.


Version 6.0.0 (31-Jan-2009)

Supports Python 3 only


Version 5.5.0 (31-Jan-2009)

Supports Python 2 only


Version 5.4.2 (11-Oct-2008)

Add support for rich compare.

Add the simplest code for a module with a single function and a single class (Demo/simple.cxx)

Fix long standing bugs with Dict::iterator


Version 5.4.1 (28-Jun-2008)

Add Boolean type from Vivian De Smedt.

Patch from Dmitry Kostjuchenko to which improves PyCXX method's calling speed/performance by almost 2 times.

More PY_LONG_LONG support.

No longer allow creation of Py::Int from PY_LONG_LONG as long long cannot fit. Use Py::Long.

Py:Dict can now be constructed from a Py::Object.


Version 5.4.0 (20-Jan-2007)

PyCXX has a new BSD license to make it open source compatible. Many thanks to Sebastian Sauer for bring this matter to our attention and to Paul Dubios for working with the LLNL people to get the license changed.

Fix compilation issues with GCC 4.1 found on FC6.

Fix compilation issues caused by problems in IRIX header files.

Add PY_LONG_LONG support from patch contributed by Dmitry Kostjuchenko.

Version 5.3.6 (21-Oct-2006)

Add support for Python 2.5

Add support for PY_LONG_LONG to Py::Int()

Version 5.3.5 (2-Oct-2005)

More changes to keep GCC 4.0 happy - no warning should be report

Version 5.3.4 (29-Aug-2005)

Add interator support - thanks to Helmut Jarausch - see pycxx_iter demo

Allow an extension to be part of a python package

Allow creation of Exception hierachies

Fix problem compiling with GCC 2.9X

Fix uninitialise memory problem

Work around compile problems with the example and GCC 4.0.

Version 5.3.3 and 5.3.2

No details recorded

PyCXX V5.3.1

Added fixes to support problems reported against GCC4 builds and .NET 2003 builds

Download PyCXX 5.3.1 from SourceForge.

PyCXX V5.3.0

I've added Unicode string support to PyCXX and fixed a number of reported bugs.

See the README and documentation for details.

Download PyCXX 5.3.0 from SourceForge.

-- BArry Scott, October 2004


PyCXX V5.2.0

After a long gap I have updated PyCXX (the name I prefer for CXX) to fix a number of bugs and add a small number of features.

I'm using the development of pysvn to drive the need for fixes and features in PyCXX.

-- Barry Scott, November 2003

pycxx-6.2.5/RegressionTests/mem-leak.py000644 000771 000000 00000001161 11523511652 020356 0ustar00barrywheel000000 000000 import simple import time import sys import os def report( title ): print( title ) os.system( 'ps uww -p %d' % (os.getpid(),) ) report( 'Start:' ) if sys.argv[1] == 'encode': for x in range( 1000000 ): y = '%6d-Hello-%6d' % (x, x) else: for x in range( 1000000 ): y = ('%6d-Hello-%6d' % (x, x)).encode( 'utf-8' ) report( 'InitDone:' ) if sys.argv[1] == 'encode': for x in range( 1000000 ): y = simple.encode_test( '%6d-Hello-%6d' % (x, x) ) else: for x in range( 1000000 ): y = simple.decode_test( ('%6d-Hello-%6d' % (x, x)).encode( 'utf-8' ) ) report( 'Done:' ) pycxx-6.2.5/Lib/__init__.py000644 000771 000000 00000004405 10547727605 016010 0ustar00barrywheel000000 000000 #----------------------------------------------------------------------------- # # Copyright (c) 1998 - 2007, The Regents of the University of California # Produced at the Lawrence Livermore National Laboratory # All rights reserved. # # This file is part of PyCXX. For details,see http:#cxx.sourceforge.net/. The # full copyright notice is contained in the file COPYRIGHT located at the root # of the PyCXX distribution. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # - Redistributions of source code must retain the above copyright notice, # this list of conditions and the disclaimer below. # - Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the disclaimer (as noted below) in the # documentation and/or materials provided with the distribution. # - Neither the name of the UC/LLNL nor the names of its contributors may be # used to endorse or promote products derived from this software without # specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF # CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH # DAMAGE. # #----------------------------------------------------------------------------- print """CXX is installed. The support files you need are in the PYTHON/etc/CXX directory. The include files are in the distutils include path already. Just refer to them as "CXX/CXX_Objects.h", etc. """ pycxx-6.2.5/Doc/Python2/000755 000771 000000 00000000000 12204160454 015217 5ustar00barrywheel000000 000000 pycxx-6.2.5/Doc/Python3/000755 000771 000000 00000000000 12204160454 015220 5ustar00barrywheel000000 000000 pycxx-6.2.5/Doc/Python3/make_contents.py000644 000771 000000 00000002434 11310763376 020440 0ustar00barrywheel000000 000000 all_lines = open( 'PyCXX.html' ).readlines() all_contents = [] for line in all_lines: if( line.startswith( '

' ) nested = False indent = '' cls = 'contents_h1' for line in all_contents: tag = line[0:len('

')] contents = line[len('

PyCXX: Writing Python Extensions in C++

Writing Python Extensions in C++ with PyCXX

Contents

Acknowledgments

Thank you to Geoffrey Furnish for patiently teaching me the finer points of C++ and its template facility, and his critique of PyCXX in particular. With version 4 I welcome Barry Scott as co-author. -- Paul Dubois

Paul is no longer contributing to PyCXX. Thanks for all your great work on PyCXX Paul. -- Barry Scott.

Overview

PyCXX is designed to make it easier to extend Python with C++

Use PyCXX Version 5 with Python 2 and PyCXX Version 6 with Python 3.

PyCXX is a set of C++ facilities to make it easier to write Python extensions. The chief way in which PyCXX makes it easier to write Python extensions is that it greatly increases the probability that your program will not make a reference-counting error and will not have to continually check error returns from the Python C API. PyCXX integrates Python with C++ in these ways:

  • C++ exception handling is relied on to detect errors and clean up. In a complicated function this is often a tremendous problem when writing in C. With PyCXX, we let the compiler keep track of what objects need to be dereferenced when an error occurs.
  • The Standard Template Library (STL) and its many algorithms plug and play with Python containers such as lists and tuples.
  • The optional CXX/Extensions.hxx facility allows you to replace the clumsy C tables with objects and method calls that define your modules and extension objects.

Download and Installation

Download PyCXX from http://sourceforge.net/projects/cxx/.

The distribution layout is:

DirectoryDescription
.Makefile for Unix and Windows, Release documentation
./CXXHeader files
./SrcSource files
./DocDocumentation
./DemoTesting and Demonstartion files

To use PyCXX you use its include files and add its source routines to your module.

Installation:

  • Install the PyCXX files into a directory of your choice. For example:
    Windows: C:\PyCXX
    Unix: /usr/local/PyCXX
  • Tell your compiler where the PyCXX header files are:
    Windows: cl /I=C:\PyCXX ...
    Unix: g++ -I/usr/local/PyCXX ...
  • Include PyCXX headers files in your code using the CXX prefix:
    #include "CXX/Objects.hxx"

The header file CXX/config.h may need to be adjusted for the compiler you use. As of this writing, only a fairly obscure reference to part of the standard library needs this adjustment. Unlike prior releases, PyCXX now assumes namespace support and a standard C++ library.

Example code

The Demo directory of the distribution contains examples of how to use many of the facilities in PyCXX.

In the top level folder of the PyCXX distributions are a number of makefiles that can be used to build and run the example code.

For example on Linux example_linux_py30.mak will build and run the example code.

make -f example_linux_py30.mak clean test
SourceDescription
Demo/test_simple.py, Demo/simple.cxxThe simplest code needed to create a module and classes in C++.
Demo/test_example.py, Demo/example.cxxThe original PyCXX example code. It is now the main test suite for PyCXX.
Demo/range.hxx, Demo/range.cxxImpliments the range object use by example.cxx.

PyCXX - Supporting Python 2 and Python 3

It is possible to have common code that can be compiled to work with Python 2 or Python 3.

Use PyCXX V5.5 with PYCXX_PYTHON_2TO3 defined to support Python 2.

Use PyCXX V6.0 with PYCXX_PYTHON_2TO3 defined to support Python 3.

The changes from Python 2 to Python 3 that require code changes are:

  • string is unicode only in Python 3 - Py::String API changed to match python 3 usage
  • byte is for byte date in Python 3 - Py::Bytes added to PyCXX
  • int has been removed - Py::Int has been removed from PyCXX

This means that you will need to:

  • Replace Py::Nothing with Py::None - required
  • Replace Py::Int with Py::Long - recommended
  • Replace Py::LongLong with Py::Long -recommended
  • Replace as_std_string() with as_std_string( "encoding" ) or as_std_string( NULL ) - required
  • Replace Py::String that holds non unicode data with Py::Bytes - required

Because the Py::String and Py::Byte implementations in PyCXX V5.5 allow abuses of the API it is best to test your code against PyCXX V6.0 to ensure correct API use then test against PyCXX V5.5.

Use of namespaces

All PyCXX assets are in namespace "Py". You need to include the Py:: prefix when referring to them, or include the statement:

using namespace Py;

Wrapper for standard objects: <CXX/Objects.hxx>

Header file CXX/Objects.hxx requires adding file Src/cxxsupport.cxx to your module sources. CXX/Objects.hxx provides a set of wrapper classes that allow you access to most of the Python C API using a C++ notation that closely resembles Python. For example, this Python:

d = {}
d[ "a" ] = 1
d[ "b" ] = 2
alist = d.keys()
print alist

Can be written in C++:

Py::Dict d;
Py::List alist;
d[ "a" ] = Py::Long( 1 );
d[ "b" ] = Py::Long( 2 );
alist = d.keys();
std::cout << alist << std::endl;

You can optionally use the CXX/Extensions.hxx facility described later to define Python extension modules and extension objects.

We avoid programming with Python object pointers

The essential idea is that we avoid, as much as possible, programming with pointers to Python objects, that is, variables of type PyObject *. Instead, we use instances of a family of C++ classes that represent the usual Python objects. This family is easily extendible to include new kinds of Python objects.

For example, consider the case in which we wish to write a method, taking a single integer argument, that will create a Python dict and insert into it that the integer plus one under the key value. In C we might do that as follows:

static PyObject *mymodule_addvalue( PyObject *self, PyObject *args )
{
    PyObject *d;
    PyObject *f;
    int k;
    PyArgs_ParseTuple( args, "i", &k );
    d = PyDict_New();
    if( !d )
        return NULL;

    f = PyInt_NEW( k+1 );
    if( !f )
    {
        Py_DECREF( d ); /* have to get rid of d first */
        return NULL;
    }
    if( PyDict_SetItemString( d, "value", f ) == -1 )
    {
        Py_DECREF( f );
        Py_DECREF( d );
        return NULL;
    }

    return d;
}

If you have written a significant Python extension, this tedium looks all too familiar. The vast bulk of the coding is error checking and cleanup. Now compare the same thing written in C++ using CXX/Objects.hxx. The things with Python-like names ( Long, Dict, Tuple ) are from CXX/Objects.hxx.

static PyObject *mymodule_addvalue( PyObject *self, PyObject *pargs )
{ 
    try
    {
        Tuple args( pargs ); 
        args.verify_length( 1 ); 

        Dict d; 
        Long k = args[0]; 
        d["value"] = k + 1;

        return new_reference_to( d ); 
    } 
    catch( const PyException & )
    { 
        return NULL;
    }
}

If there are not the right number of arguments or the argument is not an integer, an exception is thrown. In this case we choose to catch it and convert it into a Python exception. The C++ exception handling mechanism takes care all the cleanup.

Note that the creation of the Long k got the first argument and verified that it is an Long.

Just to peek ahead, if you wrote this method in an ExtensionModule-derived module of your own, it would be a method and it could be written even more simply:

Object addvalue( Object & self, const Tuple & args )
{
    args.verify_length( 1 );
    Dict d;
    Long k = args[0];
    d["value"] = k + 1;
    return d;
}

The basic concept is to wrap Python pointers

The basic concept of CXX/Objects.hxx is to create a wrapper around each PyObject * so that the reference counting can be done automatically, thus eliminating the most frequent source of errors. In addition, we can then add methods and operators so that Python objects can be manipulated in C++ much like you would in Python.

Each Object contains a PyObject * to which it owns a reference. When an Object is destroyed, it releases its ownership on the pointer. Since C++ calls the destructors on objects that are about to go out of scope, we are guaranteed that we will keep the reference counts right even if we unexpectedly leave a routine with an exception.

As a matter of philosophy, CXX/Objects.hxx prevents the creation of instances of its classes unless the instance will be a valid instance of its class. When an attempt is made to create an object that will not be valid, an exception is thrown.

Class Object represents the most general kind of Python object. The rest of the classes that represent Python objects inherit from it.

Object
Type
Float
Long
Complex
Char
Sequence -> SeqBase<T>
    String
    Tuple
    List
Mapping -> MapBase<T>
    Dict
Callable
Module

There are several constructors for each of these classes. For example, you can create an Long from an integer as in

Long s( 3 )

However, you can also create an instance of one of these classes using any PyObject * or another Object. If the corresponding Python object does not actually have the type desired, an exception is thrown. This is accomplished as follows. Class Object defines a virtual function accepts:

virtual bool accepts( PyObject *p )

The base class version of accepts returns true for any pointer p except 0. This means we can create an Object using any PyObject *, or from any other Object. However, if we attempt to create an Long from a PyObject *, the overridding version of accepts in class Long will only accept pointers that correspond to Python ints. Therefore if we have a Tuple t and we wish to get the first element and be sure it is an Long, we do

Long first_element = t[0]

This will not only accomplish the goal of extracting the first element of the Tuple t, but it will ensure that the result is an Long. If not, an exception is thrown. The exception mechanism is discussed later.

global methods

global methods
Returns Name( signature ) Comment
ObjectasObject( PyObject *p )Convert an owned Python pointer into a PyCXX Object
PyObject *Null()return (PyObject *)NULL
PyObject *new_reference_to( PyObject *p )Increment the reference count of p
PyObject *new_reference_to( const Object &g )Increment the reference count of g
ObjectNone()Return the Python None opject
ObjectTrue()Return the Python True opject
ObjectFalse()Return the Python False opject

Comparisons

PyCXX implements a full set of comparison operators (==, !=, >=, >, < <=) for the PyCXX objects.

BetweenAnd
ObjectObject
LongLong
Longlong
Longint
LongPY_LONG_LONG
FloatFloat
Floatdouble
SeqBasea<T>::iteratorSeqBase<T>::iterator
SeqBase<T>::const_iteratorSeqBase<T>::const_iterator
Sequence::iteratorSequence::iterator
Sequence::const_iteratorSequence::const_iterator
MapBase<T>::iteratorMapBase<T>::iterator
MapBase<T>::const_iteratorMapBase<T>::const_iterator
Mapping::iteratorMapping::iterator
Mapping::const_iteratorMapping::const_iterator

Class Object

Class Object serves as the base class for the other classes. Its default constructor constructs a Py_None, the unique object of Python type None. The interface to Object consists of a large number of methods corresponding to the operations that are defined for every Python object. In each case, the methods throw an exception if anything goes wrong.

There is no method corresponding to PyObject_SetItem with an arbitrary Python object as a key. Instead, create an instance of a more specific child of Object and use the appropriate facilities.

The comparison operators use the Python comparison function to compare values. The method is is available to test for absolute identity.

A conversion to standard library string type std::string is supplied using method as_string. Stream output of PyCXX Object instances uses this conversion, which in turn uses the Python object's str() representation.

All the numeric operators are defined on all possible combinations of Object, long, and double. These use the corresponding Python operators, and should the operation fail for some reason, an exception is thrown.

Dealing with pointers returned by the Python C API

Often, PyObject * pointers are acquired from some function, particularly functions in the Python C API. If you wish to make an object from the pointer returned by such a function, you need to know if the function returns you an owned or unowned reference. Unowned references are unusual but there are some cases where unowned references are returned.

Usually, Object and its children acquire a new reference when constructed from a PyObject *. This is usually not the right behavior if the reference comes from one of the Python C API calls.

If p is an owned reference, you can add the boolean true as an extra argument in the creation routine, Object( p, true ), or use the function asObject( p ) which returns an Object created using the owned reference. For example, the routine PyString_FromString returns an owned reference to a Python string object. You could write:

Object w = asObject( PyString_FromString( "my string" ) );

or using the constructor,

Object w( PyString_FromString( "my string" ), true );

In fact, you would never do this, since PyCXX has a class String and you can just say:

String w( "my string" );

Indeed, since most of the Python C API is similarly embodied in Object and its descendents, you probably will not use asObject all that often.

Class Object
Returns Name( signature ) Comment
Basic Methods
explicit Object( PyObject *pyob=Py_None, bool owned=false ) Construct from pointer.
explicit Object( const Object &ob ) Copycons; acquires an owned reference.
Object & operator=( const Object &rhs ) Acquires an owned reference.
Object & operator=( PyObject *rhsp ) Acquires an owned reference.
virtual ~Object() Releases the reference.
void increment_reference_count() Explicitly increment the count
void decrement_reference_count() Explicitly decrement count but not to zero
PyObject* operator*() const Lends the pointer
PyObject* ptr() const Lends the pointer
virtual bool accepts( PyObject *pyob ) const Would assignment of pyob to this object succeed?
std::string as_string() const str() representation
Python API Interface
int reference_count() const reference count
Type type() const associated type object
String str() const str() representation
String repr() const repr() representation
bool hasAttr( const std::string &s ) const hasattr( this, s )
Object getAttr( const std::string &s ) const getattr( this, s )
Object getItem( const Object &key ) const getitem( this, key )
long hashValue() const hash( this )
void setAttr( const std::string &s,
const Object &value )
this.s = value
void delAttr( const std::string &s ) del this.s
void delItem( const Object &key ) del this[key]
bool isCallable() const does this have callable behavior?
bool isList() const is this a Python list?
bool isMapping() const does this have mapping behaviors?
bool isNumeric() const does this have numeric behaviors?
bool isSequence() const does this have sequence behaviors?
bool isTrue() const is this true in the Python sense?
bool isType( const Type &t ) const is type( this ) == t?
bool isTuple() const is this a Python tuple?
bool isString() const is this a Python string?
bool isUnicode() const is this a Python Unicode string?
bool isDict() const is this a Python dictionary?
Comparison Operators
bool is( PyObject *pother ) const test for identity
bool is( const Object &other ) const test for identity
bool operator==( const Object &o2 ) const Comparisons use Python rich compare
bool operator!=( const Object &o2 ) const Comparisons use Python rich compare
bool operator>=( const Object &o2 ) const Comparisons use Python rich compare
bool operator<=( const Object &o2 ) const Comparisons use Python rich compare
bool operator<( const Object &o2 ) const Comparisons use Python rich compare
bool operator>( const Object &o2 ) const Comparisons use Python rich compare

The Basic Types

Corresponding to each of the basic Python types is a class that inherits from Object. Here are the interfaces for those types. Each of them inherits from Object and therefore has all of the inherited methods listed for Object. Where a virtual function is overridden in a class, the name is underlined.

Class Type

Class Type corresponds to Python type objects. There is no default constructor.

class Type
Returns Name and Signature Comments
explicit Type( PyObject *pyob, bool owned = false ) Constructor
explicit Type( const Object &ob ) Constructor
explicit Type( const Type &t ) Copycons
Type& operator=( const Object &rhs ) Assignment
Type& operator=( PyObject *rhsp ) Assignment
virtual bool accepts( PyObject *pyob ) const Uses PyType_Check

Class Long

Class Long, derived publically from Object, corresponds to Python type long. In Python, a long is an integer type of unlimited size. Implicit conversions to both double and long are provided, although the latter may of course fail if the number is actually too big. All constructors are explicit. The default constructor produces a Python long zero.

class Long
Returns Name and Signature Comments
explicit Long( PyObject *pyob, bool owned = false ) Constructor
explicit Long( const Long &ob ) Constructor
explicit Long( long v = 0L ) Construct from long
explicit Long( int v ) Contruct from int
explicit Long( const Object &ob ) Copycons
Long & operator=( const Object &rhs ) Assignment
Long & operator=( PyObject *rhsp ) Assignment
virtual bool accepts( PyObject *pyob ) const Based on PyLong_Check
double operator double() const Implicit conversion to double
long operator long() const Implicit conversion to long
Long & operator=( int v ) Assign from int
Long & operator=( long v ) Assign from long

Class Float

Class Float corresponds to Python floats, which in turn correspond to C double. The default constructor produces the Python float 0.0.

class Float
Returns Name and Signature Comments
explicit Float( PyObject *pyob, bool owned = false ) Constructor
Float( const Float &f )   Construct from float
explicit Float( double v=0.0 ) Construct from double
explicit Float( const Object &ob ) Copycons
Float& operator=( const Object &rhs ) Assignment
Float& operator=( PyObject *rhsp ) Assignment
virtual bool accepts( PyObject *pyob ) const Based on PyFloat_Check
double operator double() const Implicit conversion to double
Float & operator=( double v ) Assign from double
Float & operator=( int v ) Assign from int
Float & operator=( long v ) Assign from long
Float & operator=( const Long &iob ) Assign from Long

Sequences

PyCXX implements a quite sophisticated wrapper class for Python sequences. While every effort has been made to disguise the sophistication, it may pop up in the form of obscure compiler error messages, so in this documentation we will first detail normal usage and then discuss what is under the hood.

The basic idea is that we would like the subscript operator [] to work properly, and to be able to use STL-style iterators and STL algorithms across the elements of the sequence.

Sequences are implemented in terms of a templated base class, SeqBase<T>. The parameter T is the answer to the question, sequence of what? For Lists, for example, T is Object, because the most specific thing we know about an element of a List is simply that it is an Object.( Class List is defined below; it is a descendent of Object that holds a pointer to a Python list ). For strings, T is Char, which is a wrapper in turn of Python strings whose length is one.

For convenience, the word Sequence is a typedef of SeqBase<Object>.

General sequences

Suppose you are writing an extension module method that expects the first argument to be any kind of Python sequence, and you wish to return the length of that sequence. You might write:

static PyObject*
my_module_seqlen( PyObject *self, PyObject *args ) {
try
    {
    Tuple t( args );       // set up a Tuple pointing to the arguments.
    if( t.length() != 1 ) 
         throw PyException( "Incorrect number of arguments to seqlen." );
    Sequence s = t[0];   // get argument and be sure it is a sequence
    return new_reference_to( Long( s.length() ) );
    }
catch( const PyException  &)
    {
    return Py_Null;
    }
}

As we will explain later, the try/catch structure converts any errors, such as the first argument not being a sequence, into a Python exception.

Subscripting

When a sequence is subscripted, the value returned is a special kind of object which serves as a proxy object. The general idea of proxy objects is discussed in Scott Meyers' book, "More Effective C++". Proxy objects are necessary because when one subscripts a sequence it is not clear whether the value is to be used or the location assigned to. Our proxy object is even more complicated than normal because a sequence reference such as s[i] is not a direct reference to the i'th object of s.

In normal use, you are not supposed to notice this magic going on behind your back. You write:

Object t;
Sequence s;
s[2] = t + s[1]

and here is what happens: s[1] returns a proxy object. Since there is no addition operator in Object that takes a proxy as an argument, the compiler decides to invoke an automatic conversion of the proxy to an Object, which returns the desired component of s. The addition takes place, and then there is an assignment operator in the proxy class created by the s[2], and that assignment operator stuffs the result into the 2 component of s.

It is possible to fool this mechanism and end up with a compiler failing to admit that a s[i] is an Object. If that happens, you can work around it by writing Object( s[i] ), which makes the desired implicit conversion, explicit.

Iterators

Each sequence class provides the following interface. The class seqref<T> is the proxy class. We omit the details of the iterator, const_iterator, and seqref<T> here. See CXX/Objects.hxx if necessary. The purpose of most of this interface is to satisfy requirements of the STL.

The SeqBase<T> Interface

SeqBase<T> inherits from Object.

class SeqBase>T<
Type Name
typedef int size_type
typedef seqref<T> reference
typedef T const_reference
typedef seqref<T>* pointer
typedef int difference_type
virtual size_type max_size() const
virtual size_type capacity() const;
virtual void swap( SeqBase<T> &c );
virtual size_type size() const;
explicit SeqBase<T>();
explicit SeqBase<T>( PyObject *pyob, bool owned = false );
explicit SeqBase<T>( const Object &ob );
SeqBase<T> & operator=( const Object &rhs );
SeqBase<T> & operator=( PyObject *rhsp );
virtual bool accepts( PyObject *pyob ) const;
size_type length() const ;
const T operator[]( size_type index ) const;
seqref<T> operator[]( size_type index );
virtual T getItem( size_type i ) const;
virtual void setItem( size_type i, const T &ob );
SeqBase<T> repeat( int count ) const;
SeqBase<T> concat( const SeqBase<T> &other ) const ;
const T front() const;
seqref<T> front();
const T back() const;
seqref<T> back();
void verify_length( size_type required_size );
void verify_length( size_type min_size, size_type max_size );
class iterator;
iterator begin();
iterator end();
class const_iterator;
const_iterator begin() const;
const_iterator end() const;

Any heir of class Object that has a sequence behavior should inherit from class SeqBase<T>, where T is specified as the type of object that represents the individual elements of the sequence. The requirements on T are that it has a constructor that takes a PyObject *as an argument, that it has a default constructor, a copy constructor, and an assignment operator. In short, any properly defined heir of Object will work.

Classes Char and String

Python strings are unusual in that they are immutable sequences of characters. However, there is no character type per se; rather, when subscripted strings return a string of length one. To simulate this, we define two classes Char and String. The Char class represents a Python string object of length one. The String class represents a Python string, and its elements make up a sequence of Char's.

The user interface for Char is limited. Unlike String, for example, it is not a sequence.

The Char interface

Char inherits from Object. Char holds a single Unicode character.

unicodestring is a typedef for std::basic_string<Py_UNICODE>

class Char
Type Name
explicit Char( PyObject *pyob, bool owned = false )
Char( const Object &ob )
Char( int v )
Char( Py_UNICODE v )
Char( const unicodestring &v )
Char & operator=( const Object &o )
Char & operator=( PyObject *p )
Char & operator=( int v )
Char & operator=( Py_UNICODE v )
Char & operator=( unicodestring &v )
operator String() const

The String Interface

String inherits from SeqBase<Char>. String holds a sequence of Unicode characters.

The following is taken from Pythons's unicode.h.

Many of these APIs take two arguments encoding and errors. These parameters encoding and errors have the same semantics as the ones of the builtin unicode() API.

Setting encoding to NULL causes the default encoding to be used.

Error handling is set by errors which may also be set to NULL meaning to use the default handling defined for the codec. Default error handling for all builtin codecs is "strict" (ValueErrors are raised).

The codecs all use a similar interface. Only deviation from the generic ones are documented.

class String
Type Name
explicit String( PyObject *pyob, bool owned = false )
String( const Object &ob )
String()
String( const char *latin1 )
String( const char *latin1, Py_ssize_t size )
String( const std::string &latin1 )
String( const std::string &v, const char *encoding, const char *error=NULL )
String( const char *s, const char *encoding, const char *error=NULL )
String( const char *s, Py_ssize_t len, const char *encoding, const char *error=NULL )
String & operator=( const Object &o )
String & operator=( PyObject *p )
String & operator=( const unicodestring &v )
size_type size() const
size_type capacity() const
unicodestring as_unicodestring() const
std::string operator std::string() const
String encode( const char *encoding, const char *error="strict" )
std::string as_std_string( const char *encoding=NULL, const char *error="strict" ) const

Classes Byte and Bytes

Bytes corresponds to the Python type byte.

The Byte interface

Byte inherits from Object. Byte holds a single 8-bit byte of data.

class Byte
Type Name
explicit Byte( PyObject *pyob, bool owned = false )
Byte( const Object &ob )
Byte( const std::string &v )
Byte( char v )
Byte & operator=( const Object &o )
Byte & operator=( PyObject *p )
Byte & operator=( const std::string &v )
Byte & operator=( char v )
operator Bytes() const

The Bytes Interface

Bytes inherits from SeqBase<Byte>. Bytes holds a sequence of 8-bit data.

class Bytes
Type Name
explicit Bytes( PyObject *pyob, bool owned = false )
Bytes( const Object &ob )
Bytes()
Bytes( const char *v )
Bytes( const char *v, Py_ssize_t size )
Bytes( const std::string &v )
Bytes( const std::string &v, Py_ssize_t size )
Bytes( const char *v )
Bytes( const char *v, Py_ssize_t size )
Bytes & operator=( const Object &o )
Bytes & operator=( PyObject *p )
Bytes & operator=( const std::string &v )
size_type size() const
size_type capacity() const
String decode( const char *encoding, const char *error="strict" )
std::string operator std::string() const
Bytes encode( const char *encoding, const char *error="strict" )
std::string as_std_string() const

Class Tuple

Class Tuple represents Python tuples. A Tuple is a Sequence. There are two kinds of constructors: one takes a PyObject *as usual, the other takes an integer number as an argument and returns a Tuple of that length, each component initialized to Py_None. The default constructor produces an empty Tuple.

Tuples are not immutable, but attempts to assign to their components will fail if the reference count is not 1. That is, it is safe to set the elements of a Tuple you have just made, but not thereafter.

Example: create a Tuple containing( 1, 2, 4 )

Tuple t( 3 );
t[0] = Long( 1 );
t[1] = Long( 2 );
t[2] = Long( 4 );

Example: create a Tuple from a list:

Dict d
...
Tuple t( d.keys() )

Tuple inherits from Sequence.. Special run-time checks prevent modification if the reference count is greater than one.

class Tuple
Type Name Comment
virtual void setItem( int offset, const Object &ob ) setItem is overriden to handle tuples properly.
explicit Tuple( PyObject *pyob, bool owned = false )
Tuple( const Object &ob )
explicit Tuple( int size = 0 ) Create a tuple of the given size. Items initialize to Py_None. Default is an empty tuple.
explicit Tuple( const Sequence &s ) Create a tuple from any sequence.
Tuple& operator=( const Object &rhs )
Tuple& operator=( PyObject *rhsp )
Tuple getSlice( int i, int j ) const Equivalent to python's t[i:j]

Class TupleN

Class TupleN is an easy way to make a Tuple of N items.

Example: create a Tuple containing( 1, 2, 4 )

TupleN t3( Long( 1 ), Long( 2 ), Long( 3 ) );

Example: create a Tuple containing( "Hello", "World" )

TupleN t2( String( "Hello" ), String( "Hello" ) );
class TupleN
Type Name Comment
  TupleN() Tuple of 0 elements
  TupleN( const Object &ob1 ) Tuple of 1 element
  TupleN( const Object &ob1, const Object &ob2 ) Tuple of 2 elements
  TupleN( const Object &ob1, const Object &ob2, const Object &ob3 ) Tuple of 3 elements
  TupleN( const Object &ob1, const Object &ob2, const Object &ob3,
        const Object &ob4 )
Tuple of 4 elements
  TupleN( const Object &ob1, const Object &ob2, const Object &ob3,
        const Object &ob4, const Object &ob5 )
Tuple of 5 elements
  TupleN( const Object &ob1, const Object &ob2, const Object &ob3,
        const Object &ob4, const Object &ob5, const Object &ob6 )
Tuple of 6 elements
  TupleN( const Object &ob1, const Object &ob2, const Object &ob3,
        const Object &ob4, const Object &ob5, const Object &ob6,
        const Object &ob7 )
Tuple of 7 elements
  TupleN( const Object &ob1, const Object &ob2, const Object &ob3,
        const Object &ob4, const Object &ob5, const Object &ob6,
        const Object &ob7, const Object &ob8 )
Tuple of 8 elements
  TupleN( const Object &ob1, const Object &ob2, const Object &ob3,
        const Object &ob4, const Object &ob5, const Object &ob6,
        const Object &ob7, const Object &ob8, const Object &ob9 )
Tuple of 9 elements

Class List

Class List represents a Python list, and the methods available faithfully reproduce the Python API for lists. A List is a Sequence.

List inherits from Sequence.

class List
Type Name Comment
explicit List( PyObject *pyob, bool owned = false )
List( const Object &ob )
List( int size = 0 ) Create a list of the given size. Items initialized to Py_None. Default is an empty list.
List( const Sequence &s ) Create a list from any sequence.
List& operator=( const Object &rhs )
List& operator=( PyObject *rhsp )
List getSlice( int i, int j ) const
void setSlice( int i, int j, const Object &v )
void append( const Object &ob )
void insert( int i, const Object &ob )
void sort() Sorts the list in place, using Python's member function. You can also use the STL sort function on any List instance.
void reverse() Reverses the list in place, using Python's member function.

Mappings

A class MapBase<T> is used as the base class for Python objects with a mapping behavior. The key behavior of this class is the ability to set and use items by subscripting with strings. A proxy class mapref<T> is defined to produce the correct behavior for both use and assignment.

For convenience, Mapping is a typedef for MapBase<Object>.

The MapBase<T> interface

MapBase<T> inherits from Object. T should be chosen to reflect the kind of element returned by the mapping.

class MapBase<T>
Type Name Comment
T operator[]( const std::string &key ) const
mapref<T> operator[]( const std::string &key )
int length() const Number of entries.
int hasKey( const std::string &s ) const Is m[s] defined?
T getItem( const std::string &s ) const m[s]
virtual void setItem( const std::string &s, const Object &ob ) m[s] = ob
void delItem( const std::string &s ) del m[s]
void delItem( const Object &s )
List keys() const A list of the keys.
List values() const A list of the values.
List items() const Each item is a key-value pair.

Class Dict

Class Dict represents Python dictionarys. A Dict is a Mapping. Assignment to subscripts can be used to set the components.

Dict d
d["Paul Dubois"] = "( 925 )-422-5426"

Dict inherits from MapBase<Object>.

class Dict
Type Name Comment
explicit Dict( PyObject *pyob, bool owned = false )
Dict( const Dict &ob )
Dict() Creates an empty dictionary
Dict& operator=( const Object &rhs )
Dict& operator=( PyObject *rhsp )

Clsss Callable.

Class Callable provides an interface to those Python objects that support a call method. Class Module holds a pointer to a module. If you want to create an extension module, however, see the extension facility. There is a large set of numeric operators.

class Callable
TypeNameComment
explicitCallable( PyObject *pyob, bool owned = false )
Callable &operator=( const Object &rhs )
Callable &operator=( PyObject *rhsp )
Objectapply( const Tuple &args ) constCall the object with the given positional arguments
Objectapply( const Tuple &args, const Dict &kwd ) constCall the object with the given positional and keyword arguments
Objectapply( PyObject *pargs = 0 ) const Call the object with args as the arguments. Checks that pargs is a tuple.

Interface to class Module

class Module
Type Name Comment
explicit Module( PyObject *pyob, bool owned = false )
explicit Module( const std::string name ) Construct from name of module; does the import if needed.
Module( const Module &ob ) Copy constructor
Module& operator=( const Object &rhs ) Assignment
Module& operator=( PyObject *rhsp ) Assignment

Numeric interface

Unary operators for plus and minus, and binary operators +, -, *, /, and % are defined for pairs of objects and for objects with scalar integers or doubles( in either order ). Functions abs( ob ) and coerce( o1, o2 ) are also defined.

The signature for coerce is:

inline std::pair<Object,Object> coerce( const Object &a, const Object &b )

Unlike the C API function, this simply returns the pair after coercion.

Stream I/O

Any object can be printed using stream I/O, using std::ostream &operator<< ( std::ostream &os, const Object &ob ). The object's str() representation is converted to a standard string which is passed to std::ostream &operator<< ( std::ostream &os, const std::string &).

Exceptions

The Python exception facility and the C++ exception facility can be merged via the use of try/catch blocks in the bodies of extension objects and module functions.

Class Exception and its children

A set of classes is provided. Each is derived from class Exception, and represents a particular sort of Python exception, such as IndexError, RuntimeError, ValueError. Each of them( other than Exception ) has a constructor which takes an explanatory string as an argument, and is used in a throw statement such as:

throw IndexError( "Index too large in MyObject access." );

If in using a routine from the Python API, you discover that it has returned a NULL indicating an error, then Python has already set the error message. In that case you merely throw Exception.

List of Exceptions

The exception hierarchy mirrors the Python exception hierarchy. The concrete exception classes are shown here.

List of Exceptions
Type Interface for class Exception
explicit Exception()
Exception( const std::string &reason )
Exception( PyObject *exception, const std::string &reason )
void clear()
Constructors for other children of class Exception
TypeError( const std::string &reason )
IndexError( const std::string &reason )
AttributeError( const std::string &reason )
NameError( const std::string &reason )
RuntimeError( const std::string &reason )
SystemError( const std::string &reason )
KeyError( const std::string &reason )
ValueError( const std::string &reason )
OverflowError( const std::string &reason )
ZeroDivisionError( const std::string &reason )
MemoryError( const std::string &reason )
SystemExit( const std::string &reason )

Using Exceptions in extension methods

The exception facility allows you to integrate the C++ and Python exception mechanisms. To do this, you must use the style described below when writing module methods in the old C style.

Note: If using the ExtensionModule or PythonExtension mechanisms described below, the method handlers include exception handling so that you only need to use exceptions explicitly in unusual cases.

Catching Exceptions from the Python API or PyCXX.

When writing an extension module method, you can use the following boilerplate. Any exceptions caused by the Python API or PyCXX itself will be converted into a Python exception. Note that Exception is the most general of the exceptions listed above, and therefore this one catch clause will serve to catch all of them. You may wish to catch other exceptions, not in the Exception family, in the same way. If so, you need to make sure you set the error in Python before returning.

static PyObject *
some_module_method( PyObject *self, PyObject *args )
{
    Tuple a( args ); // we know args is a Tuple
    try
    {
        ...calculate something from a...
        return ...something, usually of the form new_reference_to( some Object );
    }
    catch( const Exception  &)
    {
        //Exception caught, passing it on to Python
        return None();
    }
}

How to clear an Exception

If you anticipate that an Exception may be thrown and wish to recover from it, change the catch phrase to set a reference to an Exception, and use the method clear() from class Exception to clear it.:

catch( Exception &e )
{
    e.clear();
    ...now decide what to do about it...
}

Extension Facilities

CXX/Extensions.hxx provides facilities for:

  • Creating a Python extension module
  • Creating new Python extension types

These facilities use CXX/Objects.hxx and its support file cxxsupport.cxx.

If you use CXX/Extensions.hxx you must also include source files cxxextensions.c and cxx_extensions.cxx

Creating an Python extension module

The usual method of creating a Python extension module is to declare and initialize its method table in C. This requires knowledge of the correct form for the table and the order in which entries are to be made into it, and requires casts to get everything to compile without warning. The PyCXX header file CXX/Extensions.h offers a simpler method. Here is a sample usage, in which a module named "example" is created. Note that two details are necessary:

  • The initialization function must be declared to have external C linkage and to have the expected name. This is a requirement imposed by Python
  • The ExtensionModule object must have a storage class that survives the call to the initialization function. This is most easily accomplished by using a static local inside the initialization function, as in initexample below.

To create an extension module, you inherit from class ExtensionModule templated on yourself: In the constructor, you make calls to register methods of this class with Python as extension module methods. In this example, two methods are added( this is a simplified form of the example in Demo/example.cxx ):

class example_module : public ExtensionModule<example_module>
{
public:
    example_module()
    : ExtensionModule<example_module>( "example" )
    {
        add_varargs_method( "sum", &example_module::ex_sum, "sum( arglist ) = sum of arguments" );
        add_varargs_method( "test", &example_module::ex_test, "test( arglist ) runs a test suite" );

        initialize( "documentation for the example module" );
    }

    virtual ~example_module() {}

private:
    Object ex_sum( const Tuple &a ) { ... }
    Object ex_test( const Tuple &a ) { ... }
};

To initialize the extension, you just instantiate one static instance( static so it does not destroy itself! ):

void initexample()
{
    static example_module* example = new example_module;
}

The methods can be written to take Tuples as arguments and return Objects. If exceptions occur they are trapped for you and a Python exception is generated. So, for example, the implementation of ex_sum might be:

Object ex_sum( const Tuple &a )
{
    Float f( 0.0 );
    for( int i = 0; i < a.length(); i++ )
    {
        Float g( a[i] );
        f = f + g;
    }
    return f;
}

class ExtensionModule contains methods to return itself as a Module object, or to return its dictionary.

class ExtensionModule
Type Name Comment
explicit ExtensionModule( char* name ) Create an extension module named "name"
virtual ~ExtensionModule() Destructor
Dict moduleDictionary() const Returns the module dictionary; module must be initialized.
Module module() const This module as a Module.
void add_varargs_method( char *name, method_varargs_function_t method, char *documentation="" ) Add a method to the module.
void add_keyword_method( char *name, method_keyword_function_t method, char *documentation="" Add a method that takes keywords
void initialize()( protected, call from constructor ) Initialize the module once all methods have been added.

The signatures above are:

typedef Object( T::*method_varargs_function_t )( const Tuple &args );
typedef Object( T::*method_keyword_function_t )( const Tuple &args, const Dict &kws
 );

That is, the methods take a Tuple or a Tuple and a Dict, and return an Object. The example below has an &in front of the name of the method; we found one compiler that needed this.

Creating a Python extension type

One of the great things about Python is the way you can create your own object types and have Python welcome them as first-class citizens. Unfortunately, part of the way you have to do this is not great. Key to the process is the creation of a Python "type object". All instances of this type must share a reference to this one unique type object. The type object itself has a multitude of "slots" into which the addresses of functions can be added in order to give the object the desired behavior.

Creating extension objects is of course harder since you must specify how the object behaves and give it methods. This is shown in some detail in the example range.h and range.cxx, with the test routine rangetest.cxx, in directory Demo. If you have never created a Python extension before, you should read the Extension manual first and be very familiar with Python's "special class methods". Then what follows will make more sense.

The basic idea is to inherit from PythonExtension templated on your self

class MyObject: public PythonExtension<MyObject> {...}

As a consequence:

  • MyObject is a child of PyObject, so that a MyObject* is-a PyObject*.
  • A static method check( PyObject * ) is created in class MyObject. This function returns a boolean, testing whether or not the argument is in fact a pointer to an instance of MyObject.
  • The user can connect methods of MyObject to Python so that they are methods on MyObject objects. Each such method has the signature:
    Object method_name( const Tuple &args ).
  • The user can override virtual methods of PythonExtension in order to set behaviors.
  • A method is created to handle the deletion of an instance if and when its reference count goes to zero. This method ensures the calling of the class destructor ~MyObject(), if any, and releases the memory( see below ).
  • Both automatic and heap-based instances of MyObject can be created.

Sample usage of PythonExtension

Here is a brief overview. You create a class that inherits from PythonExtension templated upon itself. You override various methods from PythonExtension to implement behaviors, such as getattr, sequence_item, etc. You can also add methods to the object that are usable from Python using a similar scheme as for module methods above.

One of the consequences of inheriting from PythonExtension is that you are inheriting from PyObject itself. So your class is-a PyObject and instances of it can be passed to the Python C API. Note: this example uses the namespace feature of PyCXX.

Hint: You can avoid needing to specify the Py:: prefix if you include the C++ statement using Py; at the top of your files.

class range: public Py::PythonExtension<range>
{
public:
    ... constructors, data, etc.
    ... methods not callable from Python
    // initializer, see below
    static void init_type();
    // override functions from PythonExtension
    virtual Py::Object repr();
    virtual Py::Object getattr( const char *name );

    virtual int sequence_length();
    virtual Py::Object sequence_item( int i );
    virtual Py::Object sequence_concat( const Py::Object &j );
    virtual Py::Object sequence_slice( int i, int j );

    // define python methods of this object
    Py::Object amethod( const Py::Tuple &args );
    Py::Object value( const Py::Tuple &args );
    Py::Object assign( const Py::Tuple &args ); 
};

To initialize the type we provide a static method that we can call from some module's initializer. We set the name, doc string, and indicate which behaviors range objects support. Then we adds the methods.

void range::init_type()
{
    behaviors().name( "range" );
    behaviors().doc( "range objects: start, stop, step" );
    behaviors().supportRepr();
    behaviors().supportGetattr();
    behaviors().supportSequenceType();

    add_varargs_method( "amethod", &range::amethod, "demonstrate how to document amethod" );
    add_varargs_method( "assign", &range::assign );
    add_varargs_method( "value", &range::value );
}

Do not forget to add the call range::init_type() to some module's init function. You will want a method in some module that can create range objects, too.

Your extension class T inherits PythonExtension<T>.

class PythonExtension<T>
Type Name Comment
virtual ~PythonExtension<T>() Destructor
PyTypeObject* type_object() const Returns the object type object.
int check( PyObject *p ) Is p a T?
Protected
void add_varargs_method( char *name, method_keyword_function_t method, char *documentation="" Add a method that takes arguments
void add_keyword_method( char *name, method_keyword_function_t method, char *documentation="" Add a method that takes keywords
static PythonType& behaviors() The type object
void initialize()( protected, call from constructor ) Initialize the module once all methods have been added.

As before the signatures for the methods are Object mymethod( const Tuple &args ) and Object mykeywordmethod( const Tuple &args, const Dict &keys ). In this case, the methods must be methods of T.

To set the behaviors of the object you override some or all of these methods from PythonExtension<T>:

virtual int print( FILE *, int );
virtual Object getattr( const char * );
virtual int setattr( const char *, const Object &);
virtual Object getattro( const Object &);
virtual int setattro( const Object &, const Object &);
virtual int compare( const Object &);
virtual Object repr();
virtual Object str();
virtual long hash();
virtual Object call( const Object &, const Object &);

// Sequence methods
virtual int sequence_length();
virtual Object sequence_concat( const Object &);
virtual Object sequence_repeat( int );
virtual Object sequence_item( int );
virtual Object sequence_slice( int, int );
virtual int sequence_ass_item( int, const Object &);
virtual int sequence_ass_slice( int, int, const Object &);

// Mapping
virtual int mapping_length();
virtual Object mapping_subscript( const Object &);
virtual int mapping_ass_subscript( const Object &, const Object &);

// Number
virtual int number_nonzero();
virtual Object number_negative();
virtual Object number_positive();
virtual Object number_absolute();
virtual Object number_invert();
virtual Object number_int();
virtual Object number_float();
virtual Object number_long();
virtual Object number_oct();
virtual Object number_hex();
virtual Object number_add( const Object &);
virtual Object number_subtract( const Object &);
virtual Object number_multiply( const Object &);
virtual Object number_divide( const Object &);
virtual Object number_remainder( const Object &);
virtual Object number_divmod( const Object &);
virtual Object number_lshift( const Object &);
virtual Object number_rshift( const Object &);
virtual Object number_and( const Object &);
virtual Object number_xor( const Object &);
virtual Object number_or( const Object &);
virtual Object number_power( const Object &, const Object &);

// Buffer
virtual int buffer_getreadbuffer( int, void** );
virtual int buffer_getwritebuffer( int, void** );
virtual int buffer_getsegcount( int* );

Note that dealloc is not one of the functions you can override. That is what your destructor is for. As noted below, dealloc behavior is provided for you by PythonExtension.

Type initialization

To initialize your type, supply a static public member function that can be called from the extension module. In that function, obtain the PythonType object by calling behaviors() and apply appropriate "support" methods from PythonType to turn on the support for that behavior or set of behaviors.

void supportPrint( void );
void supportGetattr( void );
void supportSetattr( void );
void supportGetattro( void );
void supportSetattro( void );
void supportCompare( void );
void supportRepr( void );
void supportStr( void );
void supportHash( void );
void supportCall( void );

void supportSequenceType( void );
void supportMappingType( void );
void supportNumberType( void );
void supportBufferType( void );

Then call add_varargs_method or add_keyword_method to add any methods desired to the object.

Notes on memory management and extension objects

Normal Python objects exist only on the heap. That is unfortunate, as object creation and destruction can be relatively expensive. Class PythonExtension allows creation of both local and heap-based objects.

If an extension object is created using operator new, as in:

range* my_r_ref = new range( 1, 20, 3 )

then the entity my_r_ref can be thought of as "owning" the reference created in the new object. Thus, the object will never have a reference count of zero. If the creator wishes to delete this object, they should either make sure the reference count is 1 and then do delete my_r_ref, or decrement the reference with Py_DECREF( my_r_ref ).

Should my_r_ref give up ownership by being used in an Object constructor, all will still be well. When the Object goes out of scope its destructor will be called, and that will decrement the reference count, which in turn will trigger the special dealloc routine that calls the destructor and deletes the pointer.

If the object is created with automatic scope, as in:

range my_r( 1, 20, 3 )

then my_r can be thought of as owning the reference, and when my_r goes out of scope the object will be destroyed. Of course, care must be taken not to have kept any permanent reference to this object. Fortunately, in the case of an exception, the C++ exception facility will call the destructor of my_r. Naturally, care must be taken not to end up with a dangling reference, but such objects can be created and destroyed more efficiently than heap-based PyObjects.

pycxx-6.2.5/Doc/Python3/style.css000644 000771 000000 00000003616 11146616710 017105 0ustar00barrywheel000000 000000 /* Copyright (c) 2008 Barry A. Scott */ h1, h2, h3, h4 { color: #000099; background-color: #aaaaff; } h2 { position: relative; left: 20px margin-right: 40px; } li.contents_h1 a, li.contents_h1 a:link, li.contents_h1 a:visited, li.contents_h1 a:active { font-size: x-large; font-style: bold; } li.contents_h2 a, li.contents_h2 a:link, li.contents_h2 a:visited, li.contents_h2 a:active { font-size: large; font-style: none; } body { background-color: #ffffff; width: 95%; } p { position: relative; left: 20px; width: 45em; margin-right: 40px; } pre { color: #0000cc; background-color: #eeeeee; position: relative; left: 40px; margin-right: 80px; border-style: solid; border-color: black; border-width: thin; } kbd { color: #990000; } p cite, ol cite, ul cite { font-family: monospace; font-style: normal; font-size: normal; } li { width: 43em; } li var, pre var, p var, kbd var { color: #009900; font-style: italic; } li samp, pre samp, p samp, kbd samp { color: #009900; font-weight: bold; } li p { position: relative; left: 0; } caption { font-size: x-large; font-style: bold; } table { position: relative; left: 20px; margin-right: 40px; border: solid #888888 1px; background-color: #eeeeee; } table th { border: solid #888888 1px; background-color: #88dd88; color: black; text-align: left; } table td { border: solid #888888 1px; } table td.code { border: solid #888888 1px; font-family: monospace; font-style: normal; font-size: normal; } p.param { background-color: #eeeeee; border-top: lightskyblue solid 4; } p.center { text-align: center; } pycxx-6.2.5/Doc/Python2/PyCXX.html000644 000771 000000 00000202467 11146616710 017100 0ustar00barrywheel000000 000000 Writing Python Extensions in C++ with PyCXX

Writing Python Extensions in C++

Barry Scott
Reading, Berkshire, England
barry@barrys-emacs.org

Paul F. Dubois, dubois1@llnl.gov
Lawrence Livermore National Laboratory
Livermore, California, U.S.A.

Acknowledgment

Thank you to Geoffrey Furnish for patiently teaching me the finer points of C++ and its template facility, and his critique of PyCXX in particular. With version 4 I welcome Barry Scott as co-author. -- Paul Dubois

Paul is no longer contributing to PyCXX. Thanks for all your great work on PyCXX Paul. -- Barry Scott.

Overview

PyCXX is designed to make it easier to extend Python with C++

PyCXX is a set of C++ facilities to make it easier to write Python extensions. The chief way in which PyCXX makes it easier to write Python extensions is that it greatly increases the probability that your program will not make a reference-counting error and will not have to continually check error returns from the Python C API. PyCXX integrates Python with C++ in these ways:

  • C++ exception handling is relied on to detect errors and clean up. In a complicated function this is often a tremendous problem when writing in C. With PyCXX, we let the compiler keep track of what objects need to be dereferenced when an error occurs.
  • The Standard Template Library (STL) and its many algorithms plug and play with Python containers such as lists and tuples.
  • The optional CXX_Extensions facility allows you to replace the clumsy C tables with objects and method calls that define your modules and extension objects.

Download and Installation

Download PyCXX from http://sourceforge.net/projects/cxx/.

The distribution layout is:

DirectoryDescription
.Makefile for Unix and Windows, Release documentation
./CXXHeader files
./SrcSource files
./DocDocumentation
./DemoTesting and Demonstartion files

To use PyCXX you use its include files and add its source routines to your module.

Installation:

  • Install the PyCXX files into a directory of your choice. For example:
    Windows: C:\PyCXX
    Unix: /usr/local/PyCXX
  • Tell your compiler where the PyCXX header files are:
    Windows: cl /I=C:\PyCXX ...
    Unix: g++ -I/usr/local/PyCXX ...
  • Include PyCXX headers files in your code using the CXX prefix:
    #include "CXX/Object.hxx"

The header file CXX/config.h may need to be adjusted for the compiler you use. As of this writing, only a fairly obscure reference to part of the standard library needs this adjustment. Unlike prior releases, PyCXX now assumes namespace support and a standard C++ library.

PyCXX - Supporting Python 2 and Python 3

It is possible to have common code that can be compiled to work with Python 2 or Python 3.

Use PyCXX V5.5 with PYCXX_PYTHON_2TO3 defined to support Python 2.

Use PyCXX V6.0 with PYCXX_PYTHON_2TO3 defined to support Python 3.

The changes from Python 2 to Python 3 that require code changes are:

  • string is unicode only in Python 3 - Py::String API changed to match python 3 usage
  • byte is for byte date in Python 3 - Py::Bytes added to PyCXX
  • int has been removed - Py::Int has been removed from PyCXX

This means that you will need to:

  • Replace Py::Nothing with Py::None - required
  • Replace Py::Int with Py::Long - recommended
  • Replace Py::LongLong with Py::Long -recommended
  • Replace as_std_string() with as_std_string( "encoding" ) or as_std_string( NULL ) - required
  • Replace Py::String that holds non unicode data with Py::Bytes - required

Because the Py::String and Py::Byte implementations in PyCXX V5.5 allow abuses of the API it is best to test your code against PyCXX V6.0 to ensure correct API use then test against PyCXX V5.5.

Use of namespaces

All PyCXX assets are in namespace "Py". You need to include the Py:: prefix when referring to them, or include the statement:

using namespace Py;

Wrappers for standard objects: CXX/Objects.hxx

Header file CXX/Objects.hxx requires adding file Src/cxxsupport.cxx to your module sources. CXX_Objects provides a set of wrapper classes that allow you access to most of the Python C API using a C++ notation that closely resembles Python. For example, this Python:

d = {}
d["a"] = 1
d["b"] = 2
alist = d.keys()
print alist

Can be written in C++:

Dict d;
List alist;
d["a"] = Int(1);
d["b"] = Int(2);
alist = d.keys();
std::cout << alist << std::endl;

You can optionally use the CXX/Extensions.hxx facility described later to define Python extension modules and extension objects.

We avoid programming with Python object pointers

The essential idea is that we avoid, as much as possible, programming with pointers to Python objects, that is, variables of type PyObject*. Instead, we use instances of a family of C++ classes that represent the usual Python objects. This family is easily extendible to include new kinds of Python objects.

For example, consider the case in which we wish to write a method, taking a single integer argument, that will create a Python dict and insert into it that the integer plus one under the key value. In C we might do that as follows:

static PyObject* mymodule_addvalue (PyObject* self, PyObject* args)
{
    PyObject *d;
    PyObject* f;
    int k;
    PyArgs_ParseTuple(args, "i", &k);
    d = PyDict_New();
    if (!d)
        return NULL;

    f = PyInt_NEW(k+1);
    if(!f)
    {
        Py_DECREF(d); /* have to get rid of d first */
        return NULL;
    }
    if(PyDict_SetItemString(d, "value", f) == -1)
    {
        Py_DECREF(f);
        Py_DECREF(d);
        return NULL;
    }

    return d;
}

If you have written a significant Python extension, this tedium looks all too familiar. The vast bulk of the coding is error checking and cleanup. Now compare the same thing written in C++ using CXX/Objects.hxx. The things with Python-like names (Int, Dict, Tuple) are from CXX/Objects.hxx.

static PyObject* mymodule_addvalue (PyObject* self, PyObject* pargs)
{ 
    try
    {
        Tuple args(pargs); 
        args.verify_length(1); 

        Dict d; 
        Int k = args[0]; 
        d["value"] = k + 1;

        return new_reference_to(d); 
    } 
    catch (const PyException&)
    { 
        return NULL;
    }
}

If there are not the right number of arguments or the argument is not an integer, an exception is thrown. In this case we choose to catch it and convert it into a Python exception. The C++ exception handling mechanism takes care all the cleanup.

Note that the creation of the Int k got the first argument and verified that it is an Int.

Just to peek ahead, if you wrote this method in an ExtensionModule-derived module of your own, it would be a method and it could be written even more simply:

Object addvalue (Object & self, const Tuple & args)
{
    args.verify_length(1);
    Dict d;
    Int k = args[0];
    d["value"] = k + 1;
    return d;
}

The basic concept is to wrap Python pointers

The basic concept of CXX/Objects.hxx is to create a wrapper around each PyObject * so that the reference counting can be done automatically, thus eliminating the most frequent source of errors. In addition, we can then add methods and operators so that Python objects can be manipulated in C++ much like you would in Python.

Each Object contains a PyObject * to which it owns a reference. When an Object is destroyed, it releases its ownership on the pointer. Since C++ calls the destructors on objects that are about to go out of scope, we are guaranteed that we will keep the reference counts right even if we unexpectedly leave a routine with an exception.

As a matter of philosophy, CXX/Objects.hxx prevents the creation of instances of its classes unless the instance will be a valid instance of its class. When an attempt is made to create an object that will not be valid, an exception is thrown.

Class Object represents the most general kind of Python object. The rest of the classes that represent Python objects inherit from it.

Object
Type
Int
Float
Long
Complex
Char
Sequence -> SeqBase<T>
    String
    Tuple
    List
Mapping -> MapBase<T>
    Dict
Callable
Module

There are several constructors for each of these classes. For example, you can create an Int from an integer as in

Int s(3)

However, you can also create an instance of one of these classes using any PyObject* or another Object. If the corresponding Python object does not actually have the type desired, an exception is thrown. This is accomplished as follows. Class Object defines a virtual function accepts:

virtual bool accepts(PyObject* p)

The base class version of accepts returns true for any pointer p except 0. This means we can create an Object using any PyObject *, or from any other Object. However, if we attempt to create an Int from a PyObject *, the overridding version of accepts in class Int will only accept pointers that correspond to Python ints. Therefore if we have a Tuple t and we wish to get the first element and be sure it is an Int, we do

Int first_element = t[0]

This will not only accomplish the goal of extracting the first element of the Tuple t, but it will ensure that the result is an Int. If not, an exception is thrown. The exception mechanism is discussed later.

Class Object

Class Object serves as the base class for the other classes. Its default constructor constructs a Py_None, the unique object of Python type None. The interface to Object consists of a large number of methods corresponding to the operations that are defined for every Python object. In each case, the methods throw an exception if anything goes wrong.

There is no method corresponding to PyObject_SetItem with an arbitrary Python object as a key. Instead, create an instance of a more specific child of Object and use the appropriate facilities.

The comparison operators use the Python comparison function to compare values. The method is is available to test for absolute identity.

A conversion to standard library string type std::string is supplied using method as_string. Stream output of PyCXX Object instances uses this conversion, which in turn uses the Python object's str() representation.

All the numeric operators are defined on all possible combinations of Object, long, and double. These use the corresponding Python operators, and should the operation fail for some reason, an exception is thrown.

Dealing with pointers returned by the Python C API

Often, PyObject * pointers are acquired from some function, particularly functions in the Python C API. If you wish to make an object from the pointer returned by such a function, you need to know if the function returns you an owned or unowned reference. Unowned references are unusual but there are some cases where unowned references are returned.

Usually, Object and its children acquire a new reference when constructed from a PyObject *. This is usually not the right behavior if the reference comes from one of the Python C API calls.

If p is an owned reference, you can add the boolean true as an extra argument in the creation routine, Object(p, true), or use the function asObject(p) which returns an Object created using the owned reference. For example, the routine PyString_FromString returns an owned reference to a Python string object. You could write:

Object w = asObject( PyString_FromString("my string") );

or using the constructor,

Object w( PyString_FromString("my string"), true );

In fact, you would never do this, since PyCXX has a class String and you can just say:

String w( "my string" );

Indeed, since most of the Python C API is similarly embodied in Object and its descendents, you probably will not use asObject all that often.

Table 1: Class Object

Returns Name(signature) Comment

Basic Methods

explicit Object (PyObject* pyob=Py_None, bool owned=false) Construct from pointer.
explicit Object (const Object& ob) Copycons; acquires an owned reference.
Object& operator= (const Object& rhs) Acquires an owned reference.
Object& operator= (PyObject* rhsp) Acquires an owned reference.
virtual ~Object () Releases the reference.
void increment_reference_count() Explicitly increment the count
void decrement_reference_count() Explicitly decrement count but not to zero
PyObject* operator* () const Lends the pointer
PyObject* ptr () const Lends the pointer
virtual bool accepts (PyObject *pyob) const Would assignment of pyob to this object succeed?
std::string as_string() const str() representation
Python API Interface
int reference_count () const reference count
Type type () const associated type object
String str () const str() representation
String repr () const repr () representation
bool hasAttr (const std::string& s) const hasattr(this, s)
Object getAttr (const std::string& s) const getattr(this, s)
Object getItem (const Object& key) const getitem(this, key)
long hashValue () const hash(this)
void setAttr (const std::string& s,
const Object& value)
this.s = value
void delAttr (const std::string& s) del this.s
void delItem (const Object& key) del this[key]
bool isCallable () const does this have callable behavior?
bool isList () const is this a Python list?
bool isMapping () const does this have mapping behaviors?
bool isNumeric () const does this have numeric behaviors?
bool isSequence () const does this have sequence behaviors?
bool isTrue () const is this true in the Python sense?
bool isType (const Type& t) const is type(this) == t?
bool isTuple() const is this a Python tuple?
bool isString() const is this a Python string?
bool isUnicode() const is this a Python Unicode string?
bool isDict() const is this a Python dictionary?
Comparison Operators
bool is(PyObject* pother) const test for identity
bool is(const Object& other) const test for identity
bool operator==(const Object& o2) const Comparisons use Python cmp
bool operator!=(const Object& o2) const Comparisons use Python cmp
bool operator>=(const Object& o2) const Comparisons use Python cmp
bool operator<=(const Object& o2) const Comparisons use Python cmp
bool operator<(const Object& o2) const Comparisons use Python cmp
bool operator>(const Object& o2) const Comparisons use Python cmp

The Basic Types

Corresponding to each of the basic Python types is a class that inherits from Object. Here are the interfaces for those types. Each of them inherits from Object and therefore has all of the inherited methods listed for Object. Where a virtual function is overridden in a class, the name is underlined.

Class Type

Class Type corresponds to Python type objects. There is no default constructor.

Table 2: class Type

Returns Name and Signature Comments
explicit Type (PyObject* pyob, bool owned = false) Constructor
explicit Type (const Object& ob) Constructor
explicit Type(const Type& t) Copycons
Type& operator= (const Object& rhs) Assignment
Type& operator= (PyObject* rhsp) Assignment
virtual bool accepts (PyObject *pyob) const Uses PyType_Check

Class Int

Class Int, derived publically from Object, corresponds to Python ints. Note that the latter correspond to C long ints. Class Int has an implicit user-defined conversion to long int. All constructors, on the other hand, are explicit. The default constructor creates a Python int zero.

Table 3: class Int

Returns Name and Signature Comments
explicit Int (PyObject *pyob, bool owned= false, bool owned = false) Constructor
explicit Int (const Int& ob) Constructor
explicit Int (long v = 0L) Construct from long
explicit Int (int v) Contruct from int
explicit Int (const Object& ob) Copycons
Int& operator= (const Object& rhs) Assignment
Int& operator= (PyObject* rhsp) Assignment
virtual bool   (PyObject *pyob) const Based on PyInt_Check
long operator long() const Implicit conversion to long int
Int& operator= (int v) Assign from int
Int& operator= (long v) Assign from long

Class Long

Class Long, derived publically from Object, corresponds to Python type long. In Python, a long is an integer type of unlimited size, and is usually used for applications such as cryptography, not as a normal integer. Implicit conversions to both double and long are provided, although the latter may of course fail if the number is actually too big. All constructors are explicit. The default constructor produces a Python long zero.

Table 4: Class Long

Returns Name and Signature Comments
explicit Long (PyObject *pyob, bool owned = false) Constructor
explicit Long (const Int& ob) Constructor
explicit Long (long v = 0L) Construct from long
explicit Long (int v) Contruct from int
explicit Long (const Object& ob) Copycons
Long& operator= (const Object& rhs) Assignment
Long& operator= (PyObject* rhsp) Assignment
virtual bool (PyObject *pyob) const Based on PyLong_Check
double operator double() const Implicit conversion to double
long operator long() const Implicit conversion to long
Long& operator= (int v) Assign from int
Long& operator= (long v) Assign from long

Class Float

Class Float corresponds to Python floats, which in turn correspond to C double. The default constructor produces the Python float 0.0.

Table 5: Class Float

Returns Name and Signature Comments
explicit Float (PyObject *pyob, bool owned = false) Constructor
Float (const Float& f)   Construct from float
explicit Float (double v=0.0) Construct from double
explicit Float (const Object& ob) Copycons
Float& operator= (const Object& rhs) Assignment
Float& operator= (PyObject* rhsp) Assignment
virtual bool accepts (PyObject *pyob) const Based on PyFloat_Check
double operator double () const Implicit conversion to double
Float& operator= (double v) Assign from double
Float& operator= (int v) Assign from int
Float& operator= (long v) Assign from long
Float& operator= (const Int& iob) Assign from Int

Sequences

PyCXX implements a quite sophisticated wrapper class for Python sequences. While every effort has been made to disguise the sophistication, it may pop up in the form of obscure compiler error messages, so in this documentation we will first detail normal usage and then discuss what is under the hood.

The basic idea is that we would like the subscript operator [] to work properly, and to be able to use STL-style iterators and STL algorithms across the elements of the sequence.

Sequences are implemented in terms of a templated base class, SeqBase<T>. The parameter T is the answer to the question, sequence of what? For Lists, for example, T is Object, because the most specific thing we know about an element of a List is simply that it is an Object. (Class List is defined below; it is a descendent of Object that holds a pointer to a Python list). For strings, T is Char, which is a wrapper in turn of Python strings whose length is one.

For convenience, the word Sequence is a typedef of SeqBase<Object>.

General sequences

Suppose you are writing an extension module method that expects the first argument to be any kind of Python sequence, and you wish to return the length of that sequence. You might write:

static PyObject*
my_module_seqlen (PyObject *self, PyObject* args) {
try
    {
    Tuple t(args);       // set up a Tuple pointing to the arguments.
    if(t.length() != 1) 
         throw PyException("Incorrect number of arguments to seqlen.");
    Sequence s = t[0];   // get argument and be sure it is a sequence
    return new_reference_to(Int(s.length()));
    }
catch(const PyException&)
    {
    return Py_Null;
    }
}

As we will explain later, the try/catch structure converts any errors, such as the first argument not being a sequence, into a Python exception.

Subscripting

When a sequence is subscripted, the value returned is a special kind of object which serves as a proxy object. The general idea of proxy objects is discussed in Scott Meyers' book, "More Effective C++". Proxy objects are necessary because when one subscripts a sequence it is not clear whether the value is to be used or the location assigned to. Our proxy object is even more complicated than normal because a sequence reference such as s[i] is not a direct reference to the i'th object of s.

In normal use, you are not supposed to notice this magic going on behind your back. You write:

Object t;
Sequence s;
s[2] = t + s[1]

and here is what happens: s[1] returns a proxy object. Since there is no addition operator in Object that takes a proxy as an argument, the compiler decides to invoke an automatic conversion of the proxy to an Object, which returns the desired component of s. The addition takes place, and then there is an assignment operator in the proxy class created by the s[2], and that assignment operator stuffs the result into the 2 component of s.

It is possible to fool this mechanism and end up with a compiler failing to admit that a s[i] is an Object. If that happens, you can work around it by writing Object(s[i]), which makes the desired implicit conversion, explicit.

Iterators

Each sequence class provides the following interface. The class seqref<T> is the proxy class. We omit the details of the iterator, const_iterator, and seqref<T> here. See CXX/Objects.hxx if necessary. The purpose of most of this interface is to satisfy requirements of the STL.

The SeqBase<T> Interface

SeqBase<T> inherits from Object.

Type Name
typedef int size_type
typedef seqref<T> reference
typedef T const_reference
typedef seqref<T>* pointer
typedef int difference_type
virtual size_type max_size() const
virtual size_type capacity() const;
virtual void swap(SeqBase<T>& c);
virtual size_type size () const;
explicit SeqBase<T> ();
explicit SeqBase<T> (PyObject* pyob, bool owned = false);
explicit SeqBase<T> (const Object& ob);
SeqBase<T>& operator= (const Object& rhs);
SeqBase<T>& operator= (PyObject* rhsp);
virtual bool accepts (PyObject *pyob) const;
size_type length () const ;
const T operator[](size_type index) const;
seqref<T> operator[](size_type index);
virtual T getItem (size_type i) const;
virtual void setItem (size_type i, const T& ob);
SeqBase<T> repeat (int count) const;
SeqBase<T> concat (const SeqBase<T>& other) const ;
const T front () const;
seqref<T> front();
const T back () const;
seqref<T> back();
void verify_length(size_type required_size);
void verify_length(size_type min_size, size_type max_size);
class iterator;
iterator begin ();
iterator end ();
class const_iterator;
const_iterator begin () const;
const_iterator end () const;

Any heir of class Object that has a sequence behavior should inherit from class SeqBase<T>, where T is specified as the type of object that represents the individual elements of the sequence. The requirements on T are that it has a constructor that takes a PyObject* as an argument, that it has a default constructor, a copy constructor, and an assignment operator. In short, any properly defined heir of Object will work.

Classes Char and String

Python strings are unusual in that they are immutable sequences of characters. However, there is no character type per se; rather, when subscripted strings return a string of length one. To simulate this, we define two classes Char and String. The Char class represents a Python string object of length one. The String class represents a Python string, and its elements make up a sequence of Char's.

The user interface for Char is limited. Unlike String, for example, it is not a sequence.

The Char interface

Char inherits from Object.

Type Name
explicit Char (PyObject *pyob, bool owned = false)
Char (const Object& ob)
Char (const std::string& v = "")
Char (char v)
Char (Py_UNICODE v)
Char& operator= (const std::string& v)
Char& operator= (char v)
Char& operator= (Py_UNICODE v)
Char& operator= (std::basic_string v)
operator String() const
operator std::string () const

The String Interface

String inherits from SeqBase<Char>.

Type Name
explicit String (PyObject *pyob, bool owned = false)
String (const Object& ob)
String (const std::string& v = "")
String (const std::string& v, const char *encoding, const char *error="strict")
String (const char *s, const char *encoding, const char *error="strict")
String (const char *s, int len, const char *encoding, const char *error="strict")
String (const std::string& v, std::string::size_type vsize)
String (const char* v)
String& operator= (const std::string& v)
std::string operator std::string () const
String encode( const char *encoding, const char *error="strict" )
String decode( const char *encoding, const char *error="strict" )
std::string as_std_string() const
unicodestring as_unicodestring() const

Class Tuple

Class Tuple represents Python tuples. A Tuple is a Sequence. There are two kinds of constructors: one takes a PyObject* as usual, the other takes an integer number as an argument and returns a Tuple of that length, each component initialized to Py_None. The default constructor produces an empty Tuple.

Tuples are not immutable, but attempts to assign to their components will fail if the reference count is not 1. That is, it is safe to set the elements of a Tuple you have just made, but not thereafter.

Example: create a Tuple containing (1, 2, 4)

Tuple t(3)
t[0] = Int(1)
t[1] = Int(2)
t[2] = Int(4)

Example: create a Tuple from a list:

Dict d
...
Tuple t(d.keys())

The Tuple Interface

Tuple inherits from Sequence.. Special run-time checks prevent modification if the reference count is greater than one.

Type Name Comment
virtual void setItem (int offset, const Object&ob) setItem is overriden to handle tuples properly.
explicit Tuple (PyObject *pyob, bool owned = false)
Tuple (const Object& ob)
explicit Tuple (int size = 0) Create a tuple of the given size. Items initialize to Py_None. Default is an empty tuple.
explicit Tuple (const Sequence& s) Create a tuple from any sequence.
Tuple& operator= (const Object& rhs)
Tuple& operator= (PyObject* rhsp)
Tuple getSlice (int i, int j) const Equivalent to python's t[i:j]

Class List

Class List represents a Python list, and the methods available faithfully reproduce the Python API for lists. A List is a Sequence.

The List Interface

List inherits from Sequence.

Type Name Comment
explicit List (PyObject *pyob, bool owned = false)
List (const Object& ob)
List (int size = 0) Create a list of the given size. Items initialized to Py_None. Default is an empty list.
List (const Sequence& s) Create a list from any sequence.
List& operator= (const Object& rhs)
List& operator= (PyObject* rhsp)
List getSlice (int i, int j) const
void setSlice (int i, int j, const Object& v)
void append (const Object& ob)
void insert (int i, const Object& ob)
void sort () Sorts the list in place, using Python's member function. You can also use the STL sort function on any List instance.
void reverse () Reverses the list in place, using Python's member function.

Mappings

A class MapBase<T> is used as the base class for Python objects with a mapping behavior. The key behavior of this class is the ability to set and use items by subscripting with strings. A proxy class mapref<T> is defined to produce the correct behavior for both use and assignment.

For convenience, Mapping is a typedef for MapBase<Object>.

The MapBase<T> interface

MapBase<T> inherits from Object. T should be chosen to reflect the kind of element returned by the mapping.

Type Name Comment
T operator[](const std::string& key) const
mapref<T> operator[](const std::string& key)
int length () const Number of entries.
int hasKey (const std::string& s) const Is m[s] defined?
T getItem (const std::string& s) const m[s]
virtual void setItem (const std::string& s, const Object& ob) m[s] = ob
void delItem (const std::string& s) del m[s]
void delItem (const Object& s)
List keys () const A list of the keys.
List values () const A list of the values.
List items () const Each item is a key-value pair.

Class Dict

Class Dict represents Python dictionarys. A Dict is a Mapping. Assignment to subscripts can be used to set the components.

Dict d
d["Paul Dubois"] = "(925)-422-5426"

Interface for Class Dict

Dict inherits from MapBase<Object>.

Type Name Comment
explicit Dict (PyObject *pyob, bool owned = false)
Dict (const Dict& ob)
Dict () Creates an empty dictionary
Dict& operator= (const Object& rhs)
Dict& operator= (PyObject* rhsp)

Other classes and facilities.

Class Callable provides an interface to those Python objects that support a call method. Class Module holds a pointer to a module. If you want to create an extension module, however, see the extension facility. There is a large set of numeric operators.

Interface to class Callable

Type Name Comment
explicit Callable (PyObject *pyob, bool owned = false)
Callable& operator= (const Object& rhs)
Callable& operator= (PyObject* rhsp)
Object apply(const Tuple& args) const Call the object with the given arguments
Object apply(PyObject* pargs = 0) const Call the object with args as the arguments. Checks that pargs is a tuple.

Interface to class Module

Type Name Comment
explicit Module (PyObject* pyob, bool owned = false)
explicit Module (const std::string name) Construct from name of module; does the import if needed.
Module (const Module& ob) Copy constructor
Module& operator= (const Object& rhs) Assignment
Module& operator= (PyObject* rhsp) Assignment

Numeric interface

Unary operators for plus and minus, and binary operators +, -, *, /, and % are defined for pairs of objects and for objects with scalar integers or doubles (in either order). Functions abs(ob) and coerce(o1, o2) are also defined.

The signature for coerce is:

inline std::pair<Object,Object> coerce(const Object& a, const Object& b)

Unlike the C API function, this simply returns the pair after coercion.

Stream I/O

Any object can be printed using stream I/O, using std::ostream& operator<< (std::ostream& os, const Object& ob). The object's str() representation is converted to a standard string which is passed to std::ostream& operator<< (std::ostream& os, const std::string&).

Exceptions

The Python exception facility and the C++ exception facility can be merged via the use of try/catch blocks in the bodies of extension objects and module functions.

Class Exception and its children

A set of classes is provided. Each is derived from class Exception, and represents a particular sort of Python exception, such as IndexError, RuntimeError, ValueError. Each of them (other than Exception) has a constructor which takes an explanatory string as an argument, and is used in a throw statement such as:

throw IndexError("Index too large in MyObject access.");

If in using a routine from the Python API, you discover that it has returned a NULL indicating an error, then Python has already set the error message. In that case you merely throw Exception.

List of Exceptions

The exception hierarchy mirrors the Python exception hierarchy. The concrete exception classes are shown here.

Type Interface for class Exception
explicit Exception()
Exception (const std::string& reason)
Exception (PyObject* exception, const std::string& reason)
void clear()
Constructors for other children of class Exception
TypeError (const std::string& reason)
IndexError (const std::string& reason)
AttributeError (const std::string& reason)
NameError (const std::string& reason)
RuntimeError (const std::string& reason)
SystemError (const std::string& reason)
KeyError (const std::string& reason)
ValueError (const std::string& reason)
OverflowError (const std::string& reason)
ZeroDivisionError (const std::string& reason)
MemoryError (const std::string& reason)
SystemExit (const std::string& reason)

Using Exceptions in extension methods

The exception facility allows you to integrate the C++ and Python exception mechanisms. To do this, you must use the style described below when writing module methods in the old C style.

Note: If using the ExtensionModule or PythonExtension mechanisms described below, the method handlers include exception handling so that you only need to use exceptions explicitly in unusual cases.

Catching Exceptions from the Python API or PyCXX.

When writing an extension module method, you can use the following boilerplate. Any exceptions caused by the Python API or PyCXX itself will be converted into a Python exception. Note that Exception is the most general of the exceptions listed above, and therefore this one catch clause will serve to catch all of them. You may wish to catch other exceptions, not in the Exception family, in the same way. If so, you need to make sure you set the error in Python before returning.

static PyObject *
some_module_method(PyObject* self, PyObject* args)
{
    Tuple a( args ); // we know args is a Tuple
    try
    {
        ...calculate something from a...
        return ...something, usually of the form new_reference_to(some Object);
    }
    catch( const Exception& )
    {
        //Exception caught, passing it on to Python
        return None();
    }
}

How to clear an Exception

If you anticipate that an Exception may be thrown and wish to recover from it, change the catch phrase to set a reference to an Exception, and use the method clear() from class Exception to clear it.:

catch( Exception& e )
{
    e.clear();
    ...now decide what to do about it...
}

Extension Facilities

CXX/Extensions.hxx provides facilities for:

  • Creating a Python extension module
  • Creating new Python extension types

These facilities use CXX/Objects.hxx and its support file cxxsupport.cxx.

If you use CXX/Extensions.hxx you must also include source files cxxextensions.c and cxx_extensions.cxx

Creating an Python extension module

The usual method of creating a Python extension module is to declare and initialize its method table in C. This requires knowledge of the correct form for the table and the order in which entries are to be made into it, and requires casts to get everything to compile without warning. The PyCXX header file CXX/Extensions.h offers a simpler method. Here is a sample usage, in which a module named "example" is created. Note that two details are necessary:

  • The initialization function must be declared to have external C linkage and to have the expected name. This is a requirement imposed by Python
  • The ExtensionModule object must have a storage class that survives the call to the initialization function. This is most easily accomplished by using a static local inside the initialization function, as in initexample below.

To create an extension module, you inherit from class ExtensionModule templated on yourself: In the constructor, you make calls to register methods of this class with Python as extension module methods. In this example, two methods are added (this is a simplified form of the example in Demo/example.cxx):

class example_module : public ExtensionModule<example_module>
{
public:
    example_module()
    : ExtensionModule<example_module>( "example" )
    {
        add_varargs_method("sum", &example_module::ex_sum, "sum(arglist) = sum of arguments");
        add_varargs_method("test", &example_module::ex_test, "test(arglist) runs a test suite");

        initialize( "documentation for the example module" );
    }

    virtual ~example_module() {}

private:
    Object ex_sum(const Tuple &a) { ... }
    Object ex_test(const Tuple &a) { ... }
};

To initialize the extension, you just instantiate one static instance (static so it does not destroy itself!):

void initexample()
{
    static example_module* example = new example_module;
}

The methods can be written to take Tuples as arguments and return Objects. If exceptions occur they are trapped for you and a Python exception is generated. So, for example, the implementation of ex_sum might be:

Object ex_sum (const Tuple &a)
{
    Float f(0.0);
    for( int i = 0; i < a.length(); i++ )
    {
        Float g(a[i]);
        f = f + g;
    }
    return f;
}

class ExtensionModule contains methods to return itself as a Module object, or to return its dictionary.

Interface to class ExtensionModule

Type Name Comment
explicit ExtensionModule (char* name) Create an extension module named "name"
virtual ~ExtensionModule () Destructor
Dict moduleDictionary() const Returns the module dictionary; module must be initialized.
Module module() const This module as a Module.
void add_varargs_method (char *name, method_varargs_function_t method, char *documentation="") Add a method to the module.
void add_keyword_method (char *name, method_keyword_function_t method, char *documentation="" Add a method that takes keywords
void initialize() (protected, call from constructor) Initialize the module once all methods have been added.

The signatures above are:

typedef Object (T::*method_varargs_function_t)( const Tuple &args );
typedef Object (T::*method_keyword_function_t)( const Tuple &args, const Dict &kws
);

That is, the methods take a Tuple or a Tuple and a Dict, and return an Object. The example below has an & in front of the name of the method; we found one compiler that needed this.

Creating a Python extension type

One of the great things about Python is the way you can create your own object types and have Python welcome them as first-class citizens. Unfortunately, part of the way you have to do this is not great. Key to the process is the creation of a Python "type object". All instances of this type must share a reference to this one unique type object. The type object itself has a multitude of "slots" into which the addresses of functions can be added in order to give the object the desired behavior.

Creating extension objects is of course harder since you must specify how the object behaves and give it methods. This is shown in some detail in the example range.h and range.cxx, with the test routine rangetest.cxx, in directory Demo. If you have never created a Python extension before, you should read the Extension manual first and be very familiar with Python's "special class methods". Then what follows will make more sense.

The basic idea is to inherit from PythonExtension templated on your self

class MyObject: public PythonExtension<MyObject> {...}

As a consequence:

  • MyObject is a child of PyObject, so that a MyObject* is-a PyObject*.
  • A static method check(PyObject*) is created in class MyObject. This function returns a boolean, testing whether or not the argument is in fact a pointer to an instance of MyObject.
  • The user can connect methods of MyObject to Python so that they are methods on MyObject objects. Each such method has the signature:
    Object method_name (const Tuple& args).
  • The user can override virtual methods of PythonExtension in order to set behaviors.
  • A method is created to handle the deletion of an instance if and when its reference count goes to zero. This method ensures the calling of the class destructor ~MyObject(), if any, and releases the memory (see below).
  • Both automatic and heap-based instances of MyObject can be created.

Sample usage of PythonExtension

Here is a brief overview. You create a class that inherits from PythonExtension templated upon itself. You override various methods from PythonExtension to implement behaviors, such as getattr, sequence_item, etc. You can also add methods to the object that are usable from Python using a similar scheme as for module methods above.

One of the consequences of inheriting from PythonExtension is that you are inheriting from PyObject itself. So your class is-a PyObject and instances of it can be passed to the Python C API. Note: this example uses the namespace feature of PyCXX.

Hint: You can avoid needing to specify the Py:: prefix if you include the C++ statement using Py; at the top of your files.

class range: public Py::PythonExtension<range>
{
public:
    ... constructors, data, etc.
    ... methods not callable from Python
    // initializer, see below
    static void init_type();
    // override functions from PythonExtension
    virtual Py::Object repr();
    virtual Py::Object getattr( const char *name );

    virtual int sequence_length();
    virtual Py::Object sequence_item( int i );
    virtual Py::Object sequence_concat( const Py::Object &j );
    virtual Py::Object sequence_slice( int i, int j );

    // define python methods of this object
    Py::Object amethod (const Py::Tuple& args);
    Py::Object value (const Py::Tuple& args);
    Py::Object assign (const Py::Tuple& args); 
};

To initialize the type we provide a static method that we can call from some module's initializer. We set the name, doc string, and indicate which behaviors range objects support. Then we adds the methods.

void range::init_type()
{
    behaviors().name("range");
    behaviors().doc("range objects: start, stop, step");
    behaviors().supportRepr();
    behaviors().supportGetattr();
    behaviors().supportSequenceType();

    add_varargs_method("amethod", &range::amethod,
        "demonstrate how to document amethod");
    add_varargs_method("assign", &range::assign);
    add_varargs_method("value", &range::value);
}

Do not forget to add the call range::init_type() to some module's init function. You will want a method in some module that can create range objects, too.

Interface to PythonExtension <T>

Your extension class T inherits PythonExtension<T>.

Type Name Comment
virtual ~PythonExtension<T>() Destructor
PyTypeObject* type_object() const Returns the object type object.
int check (PyObject* p) Is p a T?
Protected
void add_varargs_method (char *name, method_keyword_function_t method, char *documentation="" Add a method that takes arguments
void add_keyword_method (char *name, method_keyword_function_t method, char *documentation="" Add a method that takes keywords
static PythonType& behaviors() The type object
void initialize() (protected, call from constructor) Initialize the module once all methods have been added.

As before the signatures for the methods are Object mymethod(const Tuple& args) and Object mykeywordmethod (const Tuple& args, const Dict& keys). In this case, the methods must be methods of T.

To set the behaviors of the object you override some or all of these methods from PythonExtension<T>:

virtual int print( FILE *, int );
virtual Object getattr( const char * );
virtual int setattr( const char *, const Object & );
virtual Object getattro( const Object & );
virtual int setattro( const Object &, const Object & );
virtual int compare( const Object & );
virtual int rich_compare( const Object &, int op );
virtual Object repr();
virtual Object str();
virtual long hash();
virtual Object call( const Object &, const Object & );

// Sequence methods
virtual int sequence_length();
virtual Object sequence_concat( const Object & );
virtual Object sequence_repeat( int );
virtual Object sequence_item( int );
virtual Object sequence_slice( int, int );
virtual int sequence_ass_item( int, const Object & );
virtual int sequence_ass_slice( int, int, const Object & );

// Mapping
virtual int mapping_length();
virtual Object mapping_subscript( const Object & );
virtual int mapping_ass_subscript( const Object &, const Object & );

// Number
virtual int number_nonzero();
virtual Object number_negative();
virtual Object number_positive();
virtual Object number_absolute();
virtual Object number_invert();
virtual Object number_int();
virtual Object number_float();
virtual Object number_long();
virtual Object number_oct();
virtual Object number_hex();
virtual Object number_add( const Object & );
virtual Object number_subtract( const Object & );
virtual Object number_multiply( const Object & );
virtual Object number_divide( const Object & );
virtual Object number_remainder( const Object & );
virtual Object number_divmod( const Object & );
virtual Object number_lshift( const Object & );
virtual Object number_rshift( const Object & );
virtual Object number_and( const Object & );
virtual Object number_xor( const Object & );
virtual Object number_or( const Object & );
virtual Object number_power( const Object &, const Object & );

// Buffer
virtual int buffer_getreadbuffer( int, void** );
virtual int buffer_getwritebuffer( int, void** );
virtual int buffer_getsegcount( int* );

Note that dealloc is not one of the functions you can override. That is what your destructor is for. As noted below, dealloc behavior is provided for you by PythonExtension.

Type initialization

To initialize your type, supply a static public member function that can be called from the extension module. In that function, obtain the PythonType object by calling behaviors() and apply appropriate "support" methods from PythonType to turn on the support for that behavior or set of behaviors.

void supportPrint(void);
void supportGetattr(void);
void supportSetattr(void);
void supportGetattro(void);
void supportSetattro(void);
void supportCompare(void);
void supportRichCompare(void);
void supportRepr(void);
void supportStr(void);
void supportHash(void);
void supportCall(void);

void supportSequenceType(void);
void supportMappingType(void);
void supportNumberType(void);
void supportBufferType(void);

Then call add_varargs_method or add_keyword_method to add any methods desired to the object.

Notes on memory management and extension objects

Normal Python objects exist only on the heap. That is unfortunate, as object creation and destruction can be relatively expensive. Class PythonExtension allows creation of both local and heap-based objects.

If an extension object is created using operator new, as in:

range* my_r_ref = new range(1, 20, 3)

then the entity my_r_ref can be thought of as "owning" the reference created in the new object. Thus, the object will never have a reference count of zero. If the creator wishes to delete this object, they should either make sure the reference count is 1 and then do delete my_r_ref, or decrement the reference with Py_DECREF(my_r_ref).

Should my_r_ref give up ownership by being used in an Object constructor, all will still be well. When the Object goes out of scope its destructor will be called, and that will decrement the reference count, which in turn will trigger the special dealloc routine that calls the destructor and deletes the pointer.

If the object is created with automatic scope, as in:

range my_r(1, 20, 3)

then my_r can be thought of as owning the reference, and when my_r goes out of scope the object will be destroyed. Of course, care must be taken not to have kept any permanent reference to this object. Fortunately, in the case of an exception, the C++ exception facility will call the destructor of my_r. Naturally, care must be taken not to end up with a dangling reference, but such objects can be created and destroyed more efficiently than heap-based PyObjects.

Putting it all together

The Demo directory of the distribution contains an extensive example of how to use many of the facilities in PyCXX. It also serves as a test routine. This test is not completely exhaustive but does excercise much of the facility.

pycxx-6.2.5/Doc/Python2/style.css000644 000771 000000 00000003047 11146615306 017102 0ustar00barrywheel000000 000000 /* Copyright (c) 2008-2009 Barry A. Scott */ h1, h2, h3, h4 { color: #000099; background-color: #aaaaff; } h3 { position: relative; left: 20px margin-right: 40px; } body { background-color: #ffffff; width: 95%; } p { position: relative; left: 20px; width: 45em; margin-right: 40px; } pre { color: #0000cc; background-color: #eeeeee; position: relative; left: 40px; margin-right: 80px; border-style: solid; border-color: black; border-width: thin; } kbd { color: #990000; } p cite, ol cite, ul cite { font-family: monospace; font-style: normal; font-size: normal; } li { width: 43em; } li var, pre var, p var, kbd var { color: #009900; font-style: italic; } li samp, pre samp, p samp, kbd samp { color: #009900; font-weight: bold; } li p { position: relative; left: 0; } table { position: relative; left: 20px; margin-right: 40px; border: solid #888888 1px; background-color: #eeeeee; } table th { border: solid #888888 1px; background-color: #88dd88; color: black; text-align: left; } table td { border: solid #888888 1px; } table td.code { border: solid #888888 1px; font-family: monospace; font-style: normal; font-size: normal; } p.param { background-color: #eeeeee; border-top: lightskyblue solid 4; } p.center { text-align: center; } pycxx-6.2.5/Demo/Python2/000755 000771 000000 00000000000 12204160454 015376 5ustar00barrywheel000000 000000 pycxx-6.2.5/Demo/Python3/000755 000771 000000 00000000000 12204160454 015377 5ustar00barrywheel000000 000000 pycxx-6.2.5/Demo/Python3/example.cxx000644 000771 000000 00000100451 11367330334 017564 0ustar00barrywheel000000 000000 //----------------------------------------------------------------------------- // // Copyright (c) 1998 - 2007, The Regents of the University of California // Produced at the Lawrence Livermore National Laboratory // All rights reserved. // // This file is part of PyCXX. For details, see http://cxx.sourceforge.net. The // full copyright notice is contained in the file COPYRIGHT located at the root // of the PyCXX distribution. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // - Redistributions of source code must retain the above copyright notice, // this list of conditions and the disclaimer below. // - Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the disclaimer (as noted below) in the // documentation and/or materials provided with the distribution. // - Neither the name of the UC/LLNL nor the names of its contributors may be // used to endorse or promote products derived from this software without // specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF // CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH // DAMAGE. // //----------------------------------------------------------------------------- #ifdef _MSC_VER // disable warning C4786: symbol greater than 255 character, // nessesary to ignore as causes lots of warning #pragma warning(disable: 4786) #endif #include "CXX/Objects.hxx" #include "CXX/Extensions.hxx" #include #include "range.hxx" // Extension object #include "test_assert.hxx" extern void test_extension_object(); #include void test_compare() { test_assert( "compare == true", true, Py::Long( 100 ) == Py::Long( 100 ) ); test_assert( "compare == false", false, Py::Long( 100 ) == Py::Long( 101 ) ); test_assert( "compare != true", true, Py::Long( 100 ) != Py::Long( 101 ) ); test_assert( "compare != false", false, Py::Long( 100 ) != Py::Long( 100 ) ); test_assert( "compare < true", true, Py::Long( 100 ) < Py::Long( 101 ) ); test_assert( "compare < false", false, Py::Long( 100 ) < Py::Long( 99 ) ); test_assert( "compare <= true", true, Py::Long( 100 ) <= Py::Long( 101 ) ); test_assert( "compare <= true", true, Py::Long( 100 ) <= Py::Long( 100 ) ); test_assert( "compare <= false", false, Py::Long( 100 ) <= Py::Long( 99 ) ); test_assert( "compare > true", true, Py::Long( 100 ) > Py::Long( 99 ) ); test_assert( "compare > false", false, Py::Long( 100 ) > Py::Long( 101 ) ); test_assert( "compare >= true", true, Py::Long( 100 ) >= Py::Long( 99 ) ); test_assert( "compare >= true", true, Py::Long( 100 ) >= Py::Long( 100 ) ); test_assert( "compare >= false", false, Py::Long( 100 ) >= Py::Long( 101 ) ); test_assert( "compare == true", true, Py::Float( 100 ) == Py::Float( 100 ) ); test_assert( "compare == false", false, Py::Float( 100 ) == Py::Float( 101 ) ); test_assert( "compare != true", true, Py::Float( 100 ) != Py::Float( 101 ) ); test_assert( "compare != false", false, Py::Float( 100 ) != Py::Float( 100 ) ); test_assert( "compare < true", true, Py::Float( 100 ) < Py::Float( 101 ) ); test_assert( "compare < false", false, Py::Float( 100 ) < Py::Float( 99 ) ); test_assert( "compare <= true", true, Py::Float( 100 ) <= Py::Float( 101 ) ); test_assert( "compare <= true", true, Py::Float( 100 ) <= Py::Float( 100 ) ); test_assert( "compare <= false", false, Py::Float( 100 ) <= Py::Float( 99 ) ); test_assert( "compare > true", true, Py::Float( 100 ) > Py::Float( 99 ) ); test_assert( "compare > false", false, Py::Float( 100 ) > Py::Float( 101 ) ); test_assert( "compare >= true", true, Py::Float( 100 ) >= Py::Float( 99 ) ); test_assert( "compare >= true", true, Py::Float( 100 ) >= Py::Float( 100 ) ); test_assert( "compare >= false", false, Py::Float( 100 ) >= Py::Float( 101 ) ); } void test_String() { Py::String s( "hello" ); Py::Char blank = ' '; Py::String r1( "world in brief", 5 ); s = s + blank + r1; test_assert( "string concat", s, "hello world" ); s = s * 2; test_assert( "string multiple", s, "hello worldhello world" ); // test conversion std::string w = static_cast( s ); std::string w2 = s; test_assert( "string convert to std::string", w, w2 ); Py::String r2( "12345 789" ); Py::Char c6 = r2[5]; test_assert( "string convert to std::string", c6, blank ); Py::Char c7 = r2.front(); Py::Char c8 = r2.back(); } void test_boolean() { bool passed = true; Py::Object o; Py::Boolean pb1; Py::Boolean pb2; Py::String st1; Py::Long int1; bool b1; // True tests o = Py::True(); test_assert( "boolean Py::True", o.isTrue(), true ); pb1 = o; test_assert( "boolean true pybool var ", pb1 ? true : false, true ); b1 = pb1; test_assert( "boolean true bool = pybool", pb1 ? true : false, true ); pb2 = pb1; test_assert( "boolean true pybool = pybool", pb2 ? true : false, true ); pb2 = true; test_assert( "boolean true pybool = true", pb2 ? true : false, true ); test_assert( "boolean operator bool true", true, bool( pb2 ) ); // False tests o = Py::False(); test_assert( "boolean Py::False", o.isTrue(), false ); pb1 = o; test_assert( "boolean false pybool var ", pb1 ? true : false, false ); b1 = pb1; test_assert( "boolean false bool = pybool", pb1 ? true : false, false ); pb2 = pb1; test_assert( "boolean false pybool = pybool", pb2 ? true : false, false ); pb2 = false; test_assert( "boolean false pybool = false", pb2 ? true : false, false ); test_assert( "boolean operator bool false", false, bool( pb2 ) ); // conversion tests int1 = 0; pb1 = int1; test_assert( "boolean int 0", pb1 ? true : false, false ); int1 = 99; pb1 = int1; test_assert( "boolean int 99", pb1 ? true : false, true ); st1 = ""; pb1 = st1; test_assert( "boolean string \"\"", pb1 ? true : false, false ); st1 = "x"; pb1 = st1; test_assert( "boolean string \"x\"", pb1 ? true : false, true ); } void test_long() { long cxx_long1( 100 ); long cxx_long2( 0 ); long cxx_long3( 0 ); Py::Long py_long1( 100 ); Py::Long py_long2( 0 ); Py::Long py_long3( 0 ); test_assert( "long constructor", cxx_long1, py_long1.as_long() ); cxx_long2 = cxx_long1++; py_long2 = py_long1++; test_assert( "long num++", cxx_long2, py_long2.as_long() ); cxx_long2 = ++cxx_long1; py_long2 = ++py_long1; test_assert( "long ++num", cxx_long2, py_long2.as_long() ); cxx_long2 = cxx_long1--; py_long2 = py_long1--; test_assert( "long num--", cxx_long2, py_long2.as_long() ); cxx_long2 = --cxx_long1; py_long2 = --py_long1; test_assert( "long --num", cxx_long2, py_long2.as_long() ); cxx_long1 = 1000; py_long1 = 1000; test_assert( "long num =", cxx_long1, py_long1.as_long() ); // comparison tests cxx_long1 = 2; cxx_long2 = 3; cxx_long3 = 3; py_long1 = cxx_long1; py_long2 = cxx_long2; py_long3 = cxx_long3; // ------------------------------------------------------------ test_assert( "long operator ==", cxx_long2 == cxx_long3, py_long2 == py_long3 ); test_assert( "long operator ==", cxx_long2 == cxx_long3, cxx_long2 == py_long3 ); test_assert( "long operator ==", cxx_long2 == cxx_long3, py_long2 == cxx_long3 ); test_assert( "long operator ==", cxx_long1 == cxx_long3, py_long1 == py_long3 ); test_assert( "long operator ==", cxx_long1 == cxx_long3, cxx_long1 == py_long3 ); test_assert( "long operator ==", cxx_long1 == cxx_long3, py_long1 == cxx_long3 ); // ------------------------------------------------------------ test_assert( "long operator !=", cxx_long1 != cxx_long2, py_long1 != py_long2 ); test_assert( "long operator !=", cxx_long1 != cxx_long2, cxx_long1 != py_long2 ); test_assert( "long operator !=", cxx_long1 != cxx_long2, py_long1 != cxx_long2 ); test_assert( "long operator !=", cxx_long2 != cxx_long3, py_long2 != py_long3 ); test_assert( "long operator !=", cxx_long2 != cxx_long3, cxx_long2 != py_long3 ); test_assert( "long operator !=", cxx_long2 != cxx_long3, py_long2 != cxx_long3 ); // ------------------------------------------------------------ test_assert( "long operator < ", cxx_long1 < cxx_long2, py_long1 < py_long2 ); test_assert( "long operator < ", cxx_long1 < cxx_long2, cxx_long1 < py_long2 ); test_assert( "long operator < ", cxx_long1 < cxx_long2, py_long1 < cxx_long2 ); test_assert( "long operator < ", cxx_long2 < cxx_long1, py_long2 < py_long1 ); test_assert( "long operator < ", cxx_long2 < cxx_long1, cxx_long2 < py_long1 ); test_assert( "long operator < ", cxx_long2 < cxx_long1, py_long2 < cxx_long1 ); // ------------------------------------------------------------ test_assert( "long operator > ", cxx_long2 > cxx_long1, py_long2 > py_long1 ); test_assert( "long operator > ", cxx_long2 > cxx_long1, cxx_long2 > py_long1 ); test_assert( "long operator > ", cxx_long2 > cxx_long1, py_long2 > cxx_long1 ); test_assert( "long operator > ", cxx_long1 > cxx_long2, py_long1 > py_long2 ); test_assert( "long operator > ", cxx_long1 > cxx_long2, cxx_long1 > py_long2 ); test_assert( "long operator > ", cxx_long1 > cxx_long2, py_long1 > cxx_long2 ); // ------------------------------------------------------------ test_assert( "long operator <=", cxx_long1 <= cxx_long2, py_long1 <= py_long2 ); test_assert( "long operator <=", cxx_long1 <= cxx_long2, cxx_long1 <= py_long2 ); test_assert( "long operator <=", cxx_long1 <= cxx_long2, py_long1 <= cxx_long2 ); test_assert( "long operator <=", cxx_long2 <= cxx_long3, py_long2 <= py_long3 ); test_assert( "long operator <=", cxx_long2 <= cxx_long3, cxx_long2 <= py_long3 ); test_assert( "long operator <=", cxx_long2 <= cxx_long3, py_long2 <= cxx_long3 ); test_assert( "long operator <=", cxx_long2 <= cxx_long1, py_long2 <= py_long1 ); test_assert( "long operator <=", cxx_long2 <= cxx_long1, cxx_long2 <= py_long1 ); test_assert( "long operator <=", cxx_long2 <= cxx_long1, py_long2 <= cxx_long1 ); // ------------------------------------------------------------ test_assert( "long operator >=", cxx_long2 >= cxx_long1, py_long2 >= py_long1 ); test_assert( "long operator >=", cxx_long2 >= cxx_long1, cxx_long2 >= py_long1 ); test_assert( "long operator >=", cxx_long2 >= cxx_long1, py_long2 >= cxx_long1 ); test_assert( "long operator >=", cxx_long2 >= cxx_long3, py_long2 >= py_long3 ); test_assert( "long operator >=", cxx_long2 >= cxx_long3, cxx_long2 >= py_long3 ); test_assert( "long operator >=", cxx_long2 >= cxx_long3, py_long2 >= cxx_long3 ); test_assert( "long operator >=", cxx_long1 >= cxx_long2, py_long1 >= py_long2 ); test_assert( "long operator >=", cxx_long1 >= cxx_long2, cxx_long1 >= py_long2 ); test_assert( "long operator >=", cxx_long1 >= cxx_long2, py_long1 >= cxx_long2 ); // ------------------------------------------------------------ test_assert( "long operator long", cxx_long2, long( py_long2 ) ); test_assert( "long operator int", int( cxx_long2 ), int( py_long2 ) ); } void test_float() { double cxx_float1( 100 ); double cxx_float2( 0 ); double cxx_float3( 0 ); Py::Float py_float1( 100.0 ); Py::Float py_float2( 0.0 ); Py::Float py_float3( 0.0 ); test_assert( "float constructor", cxx_float1, py_float1.as_double() ); cxx_float1 = 1000; py_float1 = 1000; test_assert( "float num =", cxx_float1, py_float1.as_double() ); // comparison tests cxx_float1 = 2; cxx_float2 = 3; cxx_float3 = 3; py_float1 = cxx_float1; py_float2 = cxx_float2; py_float3 = cxx_float3; //------------------------------------------------------------ test_assert( "float operator ==", cxx_float2 == cxx_float3, py_float2 == py_float3 ); test_assert( "float operator ==", cxx_float2 == cxx_float3, cxx_float2 == py_float3 ); test_assert( "float operator ==", cxx_float2 == cxx_float3, py_float2 == cxx_float3 ); test_assert( "float operator ==", cxx_float1 == cxx_float3, py_float1 == py_float3 ); test_assert( "float operator ==", cxx_float1 == cxx_float3, cxx_float1 == py_float3 ); test_assert( "float operator ==", cxx_float1 == cxx_float3, py_float1 == cxx_float3 ); //------------------------------------------------------------ test_assert( "float operator !=", cxx_float1 != cxx_float2, py_float1 != py_float2 ); test_assert( "float operator !=", cxx_float1 != cxx_float2, cxx_float1 != py_float2 ); test_assert( "float operator !=", cxx_float1 != cxx_float2, py_float1 != cxx_float2 ); test_assert( "float operator !=", cxx_float2 != cxx_float3, py_float2 != py_float3 ); test_assert( "float operator !=", cxx_float2 != cxx_float3, cxx_float2 != py_float3 ); test_assert( "float operator !=", cxx_float2 != cxx_float3, py_float2 != cxx_float3 ); //------------------------------------------------------------ test_assert( "float operator < ", cxx_float1 < cxx_float2, py_float1 < py_float2 ); test_assert( "float operator < ", cxx_float1 < cxx_float2, cxx_float1 < py_float2 ); test_assert( "float operator < ", cxx_float1 < cxx_float2, py_float1 < cxx_float2 ); test_assert( "float operator < ", cxx_float2 < cxx_float1, py_float2 < py_float1 ); test_assert( "float operator < ", cxx_float2 < cxx_float1, cxx_float2 < py_float1 ); test_assert( "float operator < ", cxx_float2 < cxx_float1, py_float2 < cxx_float1 ); //------------------------------------------------------------ test_assert( "float operator > ", cxx_float2 > cxx_float1, py_float2 > py_float1 ); test_assert( "float operator > ", cxx_float2 > cxx_float1, cxx_float2 > py_float1 ); test_assert( "float operator > ", cxx_float2 > cxx_float1, py_float2 > cxx_float1 ); test_assert( "float operator > ", cxx_float1 > cxx_float2, py_float1 > py_float2 ); test_assert( "float operator > ", cxx_float1 > cxx_float2, cxx_float1 > py_float2 ); test_assert( "float operator > ", cxx_float1 > cxx_float2, py_float1 > cxx_float2 ); //------------------------------------------------------------ test_assert( "float operator <=", cxx_float1 <= cxx_float2, py_float1 <= py_float2 ); test_assert( "float operator <=", cxx_float1 <= cxx_float2, cxx_float2 <= py_float2 ); test_assert( "float operator <=", cxx_float1 <= cxx_float2, py_float1 <= cxx_float2 ); test_assert( "float operator <=", cxx_float2 <= cxx_float3, py_float2 <= py_float3 ); test_assert( "float operator <=", cxx_float2 <= cxx_float3, cxx_float2 <= py_float3 ); test_assert( "float operator <=", cxx_float2 <= cxx_float3, py_float2 <= cxx_float3 ); test_assert( "float operator <=", cxx_float2 <= cxx_float1, py_float2 <= py_float1 ); test_assert( "float operator <=", cxx_float2 <= cxx_float1, cxx_float2 <= py_float1 ); test_assert( "float operator <=", cxx_float2 <= cxx_float1, py_float2 <= cxx_float1 ); //------------------------------------------------------------ test_assert( "float operator >=", cxx_float2 >= cxx_float1, py_float2 >= py_float1 ); test_assert( "float operator >=", cxx_float2 >= cxx_float1, cxx_float2 >= py_float1 ); test_assert( "float operator >=", cxx_float2 >= cxx_float1, py_float2 >= cxx_float1 ); test_assert( "float operator >=", cxx_float2 >= cxx_float3, py_float2 >= py_float3 ); test_assert( "float operator >=", cxx_float2 >= cxx_float3, cxx_float2 >= py_float3 ); test_assert( "float operator >=", cxx_float2 >= cxx_float3, py_float2 >= cxx_float3 ); test_assert( "float operator >=", cxx_float1 >= cxx_float2, py_float1 >= py_float2 ); test_assert( "float operator >=", cxx_float1 >= cxx_float2, cxx_float1 >= py_float2 ); test_assert( "float operator >=", cxx_float1 >= cxx_float2, py_float1 >= cxx_float2 ); //------------------------------------------------------------ test_assert( "float operator float", cxx_float2, float( py_float2 ) ); } void test_numbers() { test_long(); test_float(); // test the basic numerical classes Py::Long i; Py::Long j(2); Py::Long k = Py::Long(3); i = 2; Py::Float a; a = 3 + i; //5.0 Py::Float b( 4.0 ); a = (1.0 + 2*a + (b*3.0)/2.0 + k)/Py::Float(5); // 4.0 i = a - 1.0; // 3 test_assert( "number calculation", i.as_long(), k.as_long() ); } void test_List() { // test the Py::List class Py::List list1; Py::List list2; test_assert( "list empty len()", list1.size(), static_cast( 0 ) ); list2.append( Py::String( "list2 index 0" ) ); list2.append( Py::String( "list2 index 1" ) ); list1.append( Py::Long( 3 ) ); list1.append( Py::Float( 6.0 ) ); list1.append( list2 ); list1.append( Py::String( "world" ) ); test_assert( "list len()", static_cast( 4 ), list1.size() ); test_assert( "list index[0]", Py::Long( 3 ), list1[0] ); test_assert( "list index[1]", Py::Float( 6.0 ), list1[1] ); test_assert( "list index[-1]", Py::String( "world" ), list1[-1] ); Py::List::iterator it1 = list1.begin(); test_assert( "list iterator not end != [0]", true, it1 != list1.end() ); test_assert( "list iterator not end == [0]", false, it1 == list1.end() ); test_assert( "list iterator compare [0]", Py::Long( 3 ), *it1 ); ++it1; test_assert( "list iterator not end != [1]", true, it1 != list1.end() ); test_assert( "list iterator not end == [1]", false, it1 == list1.end() ); test_assert( "list iterator compare [1]", Py::Float( 6.0 ), *it1 ); ++it1; test_assert( "list iterator not end != [2]", true, it1 != list1.end() ); test_assert( "list iterator not end == [2]", false, it1 == list1.end() ); test_assert( "list iterator compare [2]", list2, *it1 ); ++it1; Py::List::iterator it2 = list1.end(); test_assert( "list iterator not end != [3]", true, it1 != list1.end() ); test_assert( "list iterator not end == [3]", false, it1 == list1.end() ); test_assert( "list iterator compare [3]", Py::String( "world" ), *it1 ); ++it1; test_assert( "list iterator at end != [4]", false, it1 != list1.end() ); test_assert( "list iterator at end == [4]", true, it1 == list1.end() ); list1[ 3 ] = Py::String( "hello" ); test_assert( "list index assign", list1[ 3 ], Py::String( "hello" ) ); Py::List list3; list3 = list1 + list2; test_assert( "list operator+ count", static_cast( 6 ), list3.size() ); Py::Tuple tuple1( list1 ); test_assert( "list construct from tuple", list1.size(), tuple1.size() ); } void test_Tuple() { // test the Tuple class Py::Float f1( 1.0 ); Py::Float f2( 2.0 ); Py::Float f3( 3.0 ); Py::Tuple tuple1( 3 ); tuple1[0] = f1; // should be ok since no other reference owned tuple1[1] = f2; tuple1[2] = f3; Py::Tuple tuple2( tuple1 ); Py::Tuple::iterator it2 = tuple2.begin(); test_assert( "tuple iterator not end [0]", true, it2 != tuple2.end() ); test_assert( "tuple iterator compare [0]", Py::Float( 1.0 ), *it2 ); ++it2; test_assert( "tuple iterator not end [1]", true, it2 != tuple2.end() ); test_assert( "tuple iterator compare [1]", Py::Float( 2.0 ), *it2 ); ++it2; test_assert( "tuple iterator not end [2]", true, it2 != tuple2.end() ); test_assert( "tuple iterator compare [2]", Py::Float( 3.0 ), *it2 ); ++it2; test_assert( "tuple iterator at end [3]", true, it2 == tuple2.end() ); bool test_passed = false; Py::Tuple tuple3 = tuple1; try { tuple3[0] = Py::Long( 1 ); // should fail, tuple has multiple references } catch( Py::Exception &e ) { e.clear(); test_passed = true; } test_assert( "tuple assign exception with multiple referencese", test_passed, true ); Py::List list1( tuple1 ); test_assert( "tuple construct from list", list1.size(), tuple1.size() ); Py::TupleN t0; test_assert( "TupleN construction", 0, t0.size() ); Py::TupleN t1( Py::Long( 1 ) ); test_assert( "TupleN construction", 1, t1.size() ); Py::TupleN t2( Py::Long( 1 ), Py::Long( 2 ) ); test_assert( "TupleN construction", 2, t2.size() ); Py::TupleN t3( Py::Long( 1 ), Py::Long( 2 ), Py::Long( 3 ) ); test_assert( "TupleN construction", 3, t3.size() ); Py::TupleN t4( Py::Long( 1 ), Py::Long( 2 ), Py::Long( 3 ), Py::Long( 4 ) ); test_assert( "TupleN construction", 4, t4.size() ); Py::TupleN t5( Py::Long( 1 ), Py::Long( 2 ), Py::Long( 3 ), Py::Long( 4 ), Py::Long( 5 ) ); test_assert( "TupleN construction", 5, t5.size() ); Py::TupleN t6( Py::Long( 1 ), Py::Long( 2 ), Py::Long( 3 ), Py::Long( 4 ), Py::Long( 5 ), Py::Long( 6 ) ); test_assert( "TupleN construction", 6, t6.size() ); Py::TupleN t7( Py::Long( 1 ), Py::Long( 2 ), Py::Long( 3 ), Py::Long( 4 ), Py::Long( 5 ), Py::Long( 6 ), Py::Long( 7 ) ); test_assert( "TupleN construction", 7, t7.size() ); Py::TupleN t8( Py::Long( 1 ), Py::Long( 2 ), Py::Long( 3 ), Py::Long( 4 ), Py::Long( 5 ), Py::Long( 6 ), Py::Long( 7 ), Py::Long( 8 ) ); test_assert( "TupleN construction", 8, t8.size() ); Py::TupleN t9( Py::Long( 1 ), Py::Long( 2 ), Py::Long( 3 ), Py::Long( 4 ), Py::Long( 5 ), Py::Long( 6 ), Py::Long( 7 ), Py::Long( 8 ), Py::Long( 9 ) ); test_assert( "TupleN construction", 9, t9.size() ); } void test_Dict() { // test the Dict class Py::Dict dict1; Py::List list1; Py::String str1( "two" ); dict1[ "one" ] = Py::Long( 1 ); dict1[ str1 ] = Py::Long( 2 ); dict1[ "three" ] = Py::Long( 3 ); test_assert( "dict index[char *]", dict1[ "one" ], Py::Long( 1 ) ); test_assert( "dict index[std::string]", dict1[ std::string("one") ], Py::Long( 1 ) ); test_assert( "dict index[Py::String]", dict1[ str1 ], Py::Long( 2 ) ); test_assert( "dict keys()", dict1.keys().size(), static_cast( 3 ) ); test_assert( "dict values()", dict1.values().size(), static_cast( 3 ) ); Py::Dict::iterator it1 = dict1.begin(); test_assert( "dict iterator not end != [0]", true, it1 != dict1.end() ); test_assert( "dict iterator not end == [0]", false, it1 == dict1.end() ); ++it1; test_assert( "dict iterator not end != [1]", true, it1 != dict1.end() ); test_assert( "dict iterator not end == [1]", false, it1 == dict1.end() ); ++it1; test_assert( "dict iterator not end != [2]", true, it1 != dict1.end() ); test_assert( "dict iterator not end == [2]", false, it1 == dict1.end() ); ++it1; Py::Dict::iterator it2 = dict1.end(); bool x = it1 != it2; test_assert( "x", false, x ); test_assert( "dict iterator at end != [3]", false, it1 != dict1.end() ); test_assert( "dict iterator at end == [3]", true, it1 == dict1.end() ); list1 = dict1.values(); list1.sort(); for( long k = 1; k < 4; ++k ) { test_assert( "dict values as expected", Py::Long( list1[ k-1 ] ).as_long(), k ); } Py::Dict dict2 = dict1; dict2.clear(); test_assert( "dict clear()", dict2.keys().length(), static_cast( 0 ) ); const Py::Dict c; for (Py::Dict::const_iterator it = c.begin(); it != c.end(); ++it) { } } void test_STL() { Py::List list1; list1.append( Py::Long(5) ); list1.append( Py::Long(1) ); list1.append( Py::Long(4) ); list1.append( Py::Long(2) ); list1.append( Py::Long(3) ); list1.append( Py::Long(1) ); test_assert( "STL count", 2, std::count( list1.begin(), list1.end(), Py::Long( 1 ) ) ); Py::Dict dict1; Py::String s1( "blah" ); Py::String s2( "gorf" ); dict1[ "one" ] = s1; dict1[ "two" ] = s1; dict1[ "three" ] = s2; dict1[ "four" ] = s2; Py::Dict::iterator it( dict1.begin() ); test_assert( "STL ad hoc", true, it != dict1.end() ); while( it != dict1.end() ) { Py::Dict::value_type vt( *it ); Py::String rs = vt.second.repr(); Py::Bytes bs = rs.encode( "utf-8" ); std::string ls = bs.as_std_string(); std::cout << "STL test: " << ls << std::endl; ++it; } } void debug_check_ref_queue() { #ifdef Py_TRACE_REFS // create an element to find the queue Py::Long list_element; PyObject *p_slow = list_element.ptr(); PyObject *p_fast = p_slow; do { assert( p_slow->_ob_next->_ob_prev == p_slow ); assert( p_slow->_ob_prev->_ob_next == p_slow ); p_slow = p_slow->_ob_next; p_fast = p_slow->_ob_next->_ob_next; assert( p_slow != p_fast ); } while( p_slow != list_element.ptr() ); #endif } class example_module : public Py::ExtensionModule { public: example_module() : Py::ExtensionModule( "example" ) { range::init_type(); add_varargs_method( "string", &example_module::ex_string, "string( s ) = return string" ); add_varargs_method( "sum", &example_module::ex_sum, "sum( arglist ) = sum of arguments" ); add_varargs_method( "test", &example_module::ex_test, "test( arglist ) runs a test suite" ); add_varargs_method( "range", &example_module::new_r, "range( start, stop, step )" ); add_keyword_method( "kw", &example_module::ex_keyword, "kw()" ); initialize( "documentation for the example module" ); Py::Dict d( moduleDictionary() ); Py::Object b( Py::asObject( new range( 1, 10, 2 ) ) ); d["a_constant"] = b.getAttr("c"); d["a_range"] = b; } virtual ~example_module() {} private: Py::Object ex_keyword( const Py::Tuple &args, const Py::Dict &kws ) { std::cout << "Called with " << args.length() << " normal arguments." << std::endl; Py::List names( kws.keys() ); std::cout << "and with " << names.length() << " keyword arguments:" << std::endl; for( Py::List::size_type i=0; i< names.length(); i++ ) { Py::String name( names[i] ); std::cout << " " << name << std::endl; } return Py::Long(0); } Py::Object new_r (const Py::Tuple &rargs) { if (rargs.length() < 2 || rargs.length() > 3) { throw Py::RuntimeError("Incorrect # of args to range(start,stop [,step])."); } Py::Long start( rargs[0] ); Py::Long stop( rargs[1] ); Py::Long step( 1 ); if (rargs.length() == 3) { step = rargs[2]; } std::cout << "new_r" << " start: " << start.as_long() << " stop: " << stop.as_long() << " step: " << step.as_long() << std::endl; if( start.as_long() > stop.as_long() + 1 || step.as_long() == 0 ) { throw Py::RuntimeError("Bad arguments to range( start, stop [,step] )"); } return Py::asObject( new range( start.as_long(), stop.as_long(), step.as_long() ) ); } Py::Object ex_string( const Py::Tuple &a ) { std::cout << "ex_std::string: s1 is first arg" << std::endl; Py::Object o1( a[0] ); std::cout << "ex_string: s1.isString() " << o1.isString() << std::endl; if( o1.isString() ) { Py::String s1( o1 ); std::cout << "ex_string: s1.size() " << s1.size() << std::endl; std::cout << "ex_string: s2 is s1.encode( utf-8 )" << std::endl; Py::Bytes b1( s1.encode( "utf-8" ) ); std::cout << "ex_string: s1.isString() " << b1.isString() << std::endl; std::cout << "ex_string: s1.size() " << b1.size() << std::endl; return b1; } else { Py::Bytes b1( o1 ); std::cout << "ex_string: s1 is b1.decode( utf-8 )" << std::endl; Py::String s1( b1.decode( "utf-8" ) ); std::cout << "ex_string: s1.isString() " << s1.isString() << std::endl; std::cout << "ex_string: s1.size() " << s1.size() << std::endl; return s1; } } Py::Object ex_sum (const Py::Tuple &a) { // this is just to test the function verify_length: try { a.verify_length(0); std::cout << "I see that you refuse to give me any work to do." << std::endl; } catch (Py::Exception& e) { e.clear(); std::cout << "I will now add up your elements, oh great one." << std::endl; } Py::Float f(0.0); for( Py::Sequence::size_type i = 0; i < a.length(); i++ ) { Py::Float g (a[i]); f = f + g; } return f; } Py::Object ex_test( const Py::Tuple &args ) { debug_check_ref_queue(); std::cout << "Example Test starting" << std::endl; try { Py::String s("this should fail"); Py::Long k( s.ptr() ); throw TestError( "convert a Py::String to an Py::Long must not succeed" ); } catch( Py::TypeError &e ) { std::cout << "PASSED: Correctly caught " << Py::type(e) << std::endl; std::cout << "PASSED: Py::Exception value: " << Py::value(e) << std::endl; std::cout << "PASSED: Py::Exception traceback: " << Py::trace(e) << std::endl; e.clear(); } try { debug_check_ref_queue(); std::cout << "Start: test_compare" << std::endl; test_compare(); debug_check_ref_queue(); std::cout << "Start: test_boolean" << std::endl; test_boolean(); debug_check_ref_queue(); std::cout << "Start: test_numbers" << std::endl; test_numbers(); debug_check_ref_queue(); std::cout << "Start: test_String" << std::endl; test_String(); debug_check_ref_queue(); std::cout << "Start: test_List" << std::endl; test_List(); debug_check_ref_queue(); std::cout << "Start: test_Dict" << std::endl; test_Dict(); debug_check_ref_queue(); std::cout << "Start: test_Tuple" << std::endl; test_Tuple(); debug_check_ref_queue(); std::cout << "Start: test_STL" << std::endl; test_STL(); std::cout << "Done: test_STL" << std::endl; debug_check_ref_queue(); std::cout << "Start: test_extension_object" << std::endl; test_extension_object(); debug_check_ref_queue(); } catch( TestError &e ) { std::cout << "FAILED: Test error - " << e.m_description << std::endl; } Py::Module m("sys"); Py::Object s = m.getAttr("stdout"); Py::Object nun; nun = PyObject_CallMethod(s.ptr(), "write", "s", "Module test ok.\n"); return Py::None(); } }; #if defined( _WIN32 ) #define EXPORT_SYMBOL __declspec( dllexport ) #else #define EXPORT_SYMBOL #endif extern "C" EXPORT_SYMBOL PyObject *PyInit_example() { #if defined(PY_WIN32_DELAYLOAD_PYTHON_DLL) Py::InitialisePythonIndirectPy::Interface(); #endif static example_module *example = new example_module; return example->module().ptr(); } // symbol required for the debug version extern "C" EXPORT_SYMBOL PyObject *PyInit_example_d() { return PyInit_example(); } pycxx-6.2.5/Demo/Python3/example.def000644 000771 000000 00000000026 11146616710 017515 0ustar00barrywheel000000 000000 EXPORTS initexample pycxx-6.2.5/Demo/Python3/pycxx_iter.cxx000644 000771 000000 00000002721 11367330334 020330 0ustar00barrywheel000000 000000 #include "pycxx_iter.hxx" #include "CXX/Objects.hxx" void IterT::init_type() { behaviors().name( "IterT" ); behaviors().doc( "IterT( ini_count )" ); // you must have overwritten the virtual functions // Py::Object iter() and Py::Object iternext() behaviors().supportIter(); // set entries in the Type Table behaviors().supportRepr(); add_varargs_method( "reversed", &IterT::reversed, "reversed()" ); } class MyIterModule : public Py::ExtensionModule { public: MyIterModule() : Py::ExtensionModule( "pycxx_iter" ) { IterT::init_type(); add_varargs_method( "IterT", &MyIterModule::new_IterT, "IterT(from,last)" ); initialize( "MyIterModule documentation" ); // register with Python } virtual ~MyIterModule() {} private: Py::Object new_IterT( const Py::Tuple &args ) { if( args.length() != 2 ) { throw Py::RuntimeError( "Incorrect # of args to IterT(from,to)." ); } return Py::asObject( new IterT( Py::Long( args[0] ).as_long(), Py::Long( args[1] ).as_long() ) ); } }; #if defined( _WIN32 ) #define EXPORT_SYMBOL __declspec( dllexport ) #else #define EXPORT_SYMBOL #endif extern "C" EXPORT_SYMBOL PyObject *PyInit_pycxx_iter() { // the following constructor call registers our extension module // with the Python runtime system static MyIterModule *iter = new MyIterModule; return iter->module().ptr(); } pycxx-6.2.5/Demo/Python3/pycxx_iter.hxx000644 000771 000000 00000003613 11146616710 020336 0ustar00barrywheel000000 000000 #include "CXX/Extensions.hxx" #include #include #include class IterT : public Py::PythonExtension { int from, count, last; int fwd_iter; bool do_it_reversed; public: static void init_type(void); // announce properties and methods IterT(int _from, int _last) : from(_from) , last(_last) , fwd_iter(0) , do_it_reversed(false) {} Py::Object repr() { std::string s; std::ostringstream s_out; s_out << "IterT count(" << count << ")"; return Py::String(s_out.str()); } Py::Object reversed(const Py::Tuple&) { do_it_reversed= true; // indicate backward iteration return Py::Object(this,false); // increment the refcount } Py::Object iter() { if( do_it_reversed ) { fwd_iter = -1; do_it_reversed=false; } else fwd_iter = 1; // indicate forward iteration return Py::Object(this,false); // increment the refcount } PyObject* iternext() { int ct; if( ! fwd_iter ) return NULL; // signal StopIteration if( fwd_iter > 0 ) { if( fwd_iter == 1 ) { ct = from; count = from+1; fwd_iter=2; } else if( count <= last ) ct= count++; else return NULL; // signal StopIteration } else if( fwd_iter == -1 ) { ct = last; count = last-1; fwd_iter=-2; } else if( count >= from ) ct= count--; else return NULL; // signal StopIteration Py::Long Result(ct); Result.increment_reference_count(); return Result.ptr(); } }; pycxx-6.2.5/Demo/Python3/python.cxx000644 000771 000000 00000004776 11146616710 017467 0ustar00barrywheel000000 000000 //----------------------------------------------------------------------------- // // Copyright (c) 1998 - 2007, The Regents of the University of California // Produced at the Lawrence Livermore National Laboratory // All rights reserved. // // This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The // full copyright notice is contained in the file COPYRIGHT located at the root // of the PyCXX distribution. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // - Redistributions of source code must retain the above copyright notice, // this list of conditions and the disclaimer below. // - Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the disclaimer (as noted below) in the // documentation and/or materials provided with the distribution. // - Neither the name of the UC/LLNL nor the names of its contributors may be // used to endorse or promote products derived from this software without // specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF // CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH // DAMAGE. // //----------------------------------------------------------------------------- /* Minimal main program -- everything is loaded from the library */ #include "CXX/WrapPython.h" #include extern "C" int Py_Main(int argc, char** argv); extern "C" void initexample(); extern "C" void Py_Initialize(); int main(int argc, char** argv) { std::cout << "Greetings. Type from example import *; test()" << std::endl; Py_Initialize(); initexample(); return Py_Main(argc, argv); } pycxx-6.2.5/Demo/Python3/range.cxx000755 000771 000000 00000013015 11146616710 017227 0ustar00barrywheel000000 000000 //----------------------------------------------------------------------------- // // Copyright (c) 1998 - 2007, The Regents of the University of California // Produced at the Lawrence Livermore National Laboratory // All rights reserved. // // This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The // full copyright notice is contained in the file COPYRIGHT located at the root // of the PyCXX distribution. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // - Redistributions of source code must retain the above copyright notice, // this list of conditions and the disclaimer below. // - Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the disclaimer (as noted below) in the // documentation and/or materials provided with the distribution. // - Neither the name of the UC/LLNL nor the names of its contributors may be // used to endorse or promote products derived from this software without // specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF // CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH // DAMAGE. // //----------------------------------------------------------------------------- #ifdef _MSC_VER // disable warning C4786: symbol greater than 255 character, // nessesary to ignore as causes lots of warning #pragma warning( disable: 4786 ) #endif #include "range.hxx" // Connect range objects to Python range::range( long start, long stop, long step ) : Py::PythonExtension() , m_start( start ) , m_stop( stop ) , m_step( step ) { std::cout << "range object created " << this << " " << asString() << std::endl; } range::~range() { std::cout << "range object destroyed " << this << std::endl; } long range::length() const { return (m_stop - m_start + 1)/m_step; } long range::item( int i ) const { if( i >= length() ) // this exception stops a Python for loop over range. throw Py::IndexError("index too large"); return m_start + i * m_step; } range *range::slice( int i, int j ) const { int first = m_start + i * m_step; int last = m_start + j * m_step; return new range( first, last, m_step ); } range *range::extend( int k ) const { return new range( m_start, m_stop + k, m_step); } std::string range::asString() const { std::OSTRSTREAM s; s << "range(" << m_start << ", " << m_stop << ", " << m_step << ")" << std::ends; return std::string( s.str() ); } Py::Object range::reference_count( const Py::Tuple &args ) { return Py::Long( ob_refcnt ); } Py::Object range::c_value(const Py::Tuple&) const { Py::List result; for( int i = m_start; i <= m_stop; i += m_step ) { result.append( Py::Long(i) ); } return result; } void range::c_assign( const Py::Tuple &, const Py::Object &rhs ) { Py::Tuple w( rhs ); w.verify_length( 3 ); m_start = Py::Long( w[0] ).as_long(); m_stop = Py::Long( w[1] ).as_long(); m_step = Py::Long( w[2] ).as_long(); } Py::Object range::repr() { return Py::String( asString() ); } int range::sequence_length() { return length(); } Py::Object range::sequence_item( Py_ssize_t i ) { return Py::Long( item( i ) ); } Py::Object range::sequence_concat( const Py::Object &j ) { Py::Long k( j ); return Py::asObject( extend( k.as_long() ) ); } Py::Object range::sequence_slice( Py_ssize_t i, Py_ssize_t j ) { return Py::asObject( slice( i, j ) ); } Py::Object range::getattr( const char *name ) { if( std::string( name ) == "c" ) return Py::Float( 300.0 ); if( std::string( name ) == "start" ) return Py::Long( m_start ); return getattr_methods( name ); } // "regular" methods... Py::Object range::amethod( const Py::Tuple &t ) { t.verify_length( 1 ); Py::List result; result.append( Py::Object( this ) ); result.append( t[0] ); return result; } Py::Object range::value( const Py::Tuple &t ) { return c_value( t ); } Py::Object range::assign( const Py::Tuple &t ) { t.verify_length( 2 ); Py::Tuple t1( t[0] ); // subscripts Py::Object o2( t[1] ); // rhs; c_assign ( t1, o2 ); return Py::None(); } void range::init_type() { behaviors().name( "range" ); behaviors().doc( "range objects: start, stop, step" ); behaviors().supportRepr(); behaviors().supportGetattr(); behaviors().supportSequenceType(); add_varargs_method( "amethod", &range::amethod, "demonstrate how to document amethod" ); add_varargs_method( "assign", &range::assign ); add_varargs_method( "value", &range::value ); add_varargs_method( "reference_count", &range::reference_count ); } pycxx-6.2.5/Demo/Python3/range.hxx000755 000771 000000 00000010450 11146616710 017234 0ustar00barrywheel000000 000000 //----------------------------------------------------------------------------- // // Copyright (c) 1998 - 2007, The Regents of the University of California // Produced at the Lawrence Livermore National Laboratory // All rights reserved. // // This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The // full copyright notice is contained in the file COPYRIGHT located at the root // of the PyCXX distribution. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // - Redistributions of source code must retain the above copyright notice, // this list of conditions and the disclaimer below. // - Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the disclaimer (as noted below) in the // documentation and/or materials provided with the distribution. // - Neither the name of the UC/LLNL nor the names of its contributors may be // used to endorse or promote products derived from this software without // specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF // CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH // DAMAGE. // //----------------------------------------------------------------------------- #ifndef __r__h #define __r__h #include "CXX/Extensions.hxx" #include STR_STREAM // Making an extension object class range: public Py::PythonExtension { public: range( long start, long stop, long step = 1L ); virtual ~range(); static void init_type(void); long length() const; long item( int i ) const; range *slice( int i, int j ) const; range *extend( int k ) const; std::string asString() const; // override functions from PythonExtension virtual Py::Object repr(); virtual Py::Object getattr( const char *name ); virtual int sequence_length(); virtual Py::Object sequence_item( Py_ssize_t i ); virtual Py::Object sequence_concat( const Py::Object &j ); virtual Py::Object sequence_slice( Py_ssize_t i, Py_ssize_t j ); // define python methods of this object Py::Object amethod( const Py::Tuple &args ); Py::Object value( const Py::Tuple &args ); Py::Object assign( const Py::Tuple &args ); Py::Object reference_count( const Py::Tuple &args ); Py::Object c_value( const Py::Tuple & ) const; void c_assign( const Py::Tuple &, const Py::Object &rhs ); private: long m_start; long m_stop; long m_step; }; class RangeSequence: public Py::SeqBase { public: explicit RangeSequence (PyObject *pyob, bool owned = false): Py::SeqBase(pyob, owned) { validate(); } explicit RangeSequence(int start, int stop, int step = 1) { set (new range(start, stop, step), true); } RangeSequence(const RangeSequence& other): Py::SeqBase(*other) { validate(); } RangeSequence& operator= (const Py::Object& rhs) { return (*this = *rhs); } RangeSequence& operator= (PyObject* rhsp) { if(ptr() == rhsp) return *this; set(rhsp); return *this; } virtual bool accepts(PyObject *pyob) const { return pyob && range::check(pyob); } Py::Object value(const Py::Tuple& t) const { return static_cast(ptr())->c_value(t); } void assign(const Py::Tuple& t, const Py::Object& rhs) { static_cast(ptr())->c_assign(t, rhs); } }; #endif pycxx-6.2.5/Demo/Python3/rangetest.cxx000755 000771 000000 00000010400 11353641071 020120 0ustar00barrywheel000000 000000 //----------------------------------------------------------------------------- // // Copyright (c) 1998 - 2007, The Regents of the University of California // Produced at the Lawrence Livermore National Laboratory // All rights reserved. // // This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The // full copyright notice is contained in the file COPYRIGHT located at the root // of the PyCXX distribution. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // - Redistributions of source code must retain the above copyright notice, // this list of conditions and the disclaimer below. // - Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the disclaimer (as noted below) in the // documentation and/or materials provided with the distribution. // - Neither the name of the UC/LLNL nor the names of its contributors may be // used to endorse or promote products derived from this software without // specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF // CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH // DAMAGE. // //----------------------------------------------------------------------------- #ifdef _MSC_VER // disable warning C4786: symbol greater than 255 character, // nessesary to ignore as causes lots of warning #pragma warning( disable: 4786 ) #endif #include "CXX/Extensions.hxx" #include "range.hxx" #include "test_assert.hxx" // This test also illustrates using the Py namespace explicitly void test_extension_object() { Py::List a; // just something that is not a range... Py::ExtensionObject r1( new range( 1, 20, 3 ) ); test_assert( "extension object check() incompatible", false, range::check( a ) ); test_assert( "extension object check() incompatible", true, range::check( r1 ) ); RangeSequence r2( 1, 10, 2 ); test_assert( "extension object index", r2[ 1 ], Py::Long( 3 ) ); // calling an extension object method using getattr Py::Callable w( r2.getAttr( "amethod" ) ); { Py::Tuple args( 1 ); Py::Long j( 3 ); args[0] = j; Py::List answer( w.apply( args ) ); test_assert( "extension object amethod 1 q1", answer[0], r2 ); test_assert( "extension object amethod 1q2", answer[1], args[0] ); } { // calling an extension object method using callMemberFunction Py::Tuple args( 1 ); Py::Long j( 3 ); args[0] = j; Py::List answer( r2.callMemberFunction( "amethod", args ) ); test_assert( "extension object amethod 2 q1", answer[0], r2 ); test_assert( "extension object amethod 2 q2", answer[1], args[0] ); } Py::Tuple nv( 3 ); nv[0] = Py::Long( 1 ); nv[1] = Py::Long( 20 ); nv[2] = Py::Long( 3 ); Py::Tuple unused; Py::List r2value; r2.assign( unused, nv ); r2value = r2.value( unused ); test_assert( "extension object q3", r2value[1], Py::Long( 4 ) ); // repeat using getattr w = r2.getAttr( "assign" ); Py::Tuple the_arguments( 2 ); the_arguments[0] = unused; the_arguments[1] = nv; w.apply( the_arguments ); { Py::ExtensionObject rheap( new range( 1, 10, 2 ) ); // delete rheap } w = r2.getAttr( "value" ); Py::Tuple one_arg( 1 ); one_arg[0] = unused; r2value = w.apply( one_arg ); test_assert( "extension object q4", r2value[1], Py::Long( 4 ) ); } pycxx-6.2.5/Demo/Python3/setup.py000644 000771 000000 00000006311 11230635754 017122 0ustar00barrywheel000000 000000 #----------------------------------------------------------------------------- # # Copyright (c) 1998 - 2007, The Regents of the University of California # Produced at the Lawrence Livermore National Laboratory # All rights reserved. # # This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The # full copyright notice is contained in the file COPYRIGHT located at the root # of the PyCXX distribution. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # - Redistributions of source code must retain the above copyright notice, # this list of conditions and the disclaimer below. # - Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the disclaimer (as noted below) in the # documentation and/or materials provided with the distribution. # - Neither the name of the UC/LLNL nor the names of its contributors may be # used to endorse or promote products derived from this software without # specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF # CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH # DAMAGE. # #----------------------------------------------------------------------------- import os, sys from distutils.core import setup, Extension support_dir = os.path.normpath( os.path.join( sys.prefix, 'share', 'python%d.%d' % (sys.version_info[0],sys.version_info[1]), 'CXX') ) if os.name == 'posix': CXX_libraries = ['stdc++','m'] else: CXX_libraries = [] setup (name = "CXXDemo", version = "5.1", maintainer = "Barry Scott", maintainer_email = "barry-scott@users.sourceforge.net", description = "Demo of facility for extending Python with C++", url = "http://cxx.sourceforge.net", packages = ['CXX'], package_dir = {'CXX': '.'}, ext_modules = [ Extension('CXX.example', sources = ['example.cxx', 'range.cxx', 'rangetest.cxx', os.path.join(support_dir,'cxxsupport.cxx'), os.path.join(support_dir,'cxx_extensions.cxx'), os.path.join(support_dir,'IndirectPythonInterface.cxx'), os.path.join(support_dir,'cxxextensions.c') ], ) ] ) pycxx-6.2.5/Demo/Python3/simple.cxx000644 000771 000000 00000023547 11523511652 017432 0ustar00barrywheel000000 000000 // // Copyright (c) 2008-2010 Barry A. Scott // // // simple_moduile.cxx // // This module defines a single function. // #ifdef _MSC_VER // disable warning C4786: symbol greater than 255 character, // nessesary to ignore as causes lots of warning #pragma warning(disable: 4786) #endif #include "CXX/Objects.hxx" #include "CXX/Extensions.hxx" #include class new_style_class: public Py::PythonClass< new_style_class > { public: new_style_class( Py::PythonClassInstance *self, Py::Tuple &args, Py::Dict &kwds ) : Py::PythonClass< new_style_class >::PythonClass( self, args, kwds ) , m_value( "default value" ) { std::cout << "new_style_class c'tor Called with " << args.length() << " normal arguments." << std::endl; Py::List names( kwds.keys() ); std::cout << "and with " << names.length() << " keyword arguments:" << std::endl; for( Py::List::size_type i=0; i< names.length(); i++ ) { Py::String name( names[i] ); std::cout << " " << name << std::endl; } } virtual ~new_style_class() { std::cout << "~new_style_class." << std::endl; } static void init_type(void) { behaviors().name( "new_style_class" ); behaviors().doc( "documentation for new_style_class class" ); behaviors().supportGetattro(); behaviors().supportSetattro(); PYCXX_ADD_NOARGS_METHOD( func_noargs, new_style_class_func_noargs, "docs for func_noargs" ); PYCXX_ADD_VARARGS_METHOD( func_varargs, new_style_class_func_varargs, "docs for func_varargs" ); PYCXX_ADD_KEYWORDS_METHOD( func_keyword, new_style_class_func_keyword, "docs for func_keyword" ); PYCXX_ADD_NOARGS_METHOD( func_noargs_raise_exception, new_style_class_func_noargs_raise_exception, "docs for func_noargs_raise_exception" ); // Call to make the type ready for use behaviors().readyType(); } Py::Object new_style_class_func_noargs( void ) { std::cout << "new_style_class_func_noargs Called." << std::endl; std::cout << "value ref count " << m_value.reference_count() << std::endl; return Py::None(); } PYCXX_NOARGS_METHOD_DECL( new_style_class, new_style_class_func_noargs ) Py::Object new_style_class_func_varargs( const Py::Tuple &args ) { std::cout << "new_style_class_func_varargs Called with " << args.length() << " normal arguments." << std::endl; return Py::None(); } PYCXX_VARARGS_METHOD_DECL( new_style_class, new_style_class_func_varargs ) Py::Object new_style_class_func_keyword( const Py::Tuple &args, const Py::Dict &kwds ) { std::cout << "new_style_class_func_keyword Called with " << args.length() << " normal arguments." << std::endl; Py::List names( kwds.keys() ); std::cout << "and with " << names.length() << " keyword arguments:" << std::endl; for( Py::List::size_type i=0; i< names.length(); i++ ) { Py::String name( names[i] ); std::cout << " " << name << std::endl; } return Py::None(); } PYCXX_KEYWORDS_METHOD_DECL( new_style_class, new_style_class_func_keyword ) Py::Object new_style_class_func_noargs_raise_exception( void ) { std::cout << "new_style_class_func_noargs_raise_exception Called." << std::endl; throw Py::RuntimeError( "its an error" ); return Py::None(); } PYCXX_NOARGS_METHOD_DECL( new_style_class, new_style_class_func_noargs_raise_exception ) Py::Object getattro( const Py::String &name_ ) { std::string name( name_.as_std_string( "utf-8" ) ); if( name == "value" ) { return m_value; } else { return genericGetAttro( name_ ); } } int setattro( const Py::String &name_, const Py::Object &value ) { std::string name( name_.as_std_string( "utf-8" ) ); if( name == "value" ) { m_value = value; return 0; } else { return genericSetAttro( name_, value ); } } Py::String m_value; }; class old_style_class: public Py::PythonExtension< old_style_class > { public: old_style_class() { } virtual ~old_style_class() { } static void init_type(void) { behaviors().name( "old_style_class" ); behaviors().doc( "documentation for old_style_class class" ); behaviors().supportGetattr(); add_noargs_method( "old_style_class_func_noargs", &old_style_class::old_style_class_func_noargs ); add_varargs_method( "old_style_class_func_varargs", &old_style_class::old_style_class_func_varargs ); add_keyword_method( "old_style_class_func_keyword", &old_style_class::old_style_class_func_keyword ); } // override functions from PythonExtension virtual Py::Object getattr( const char *name ) { return getattr_methods( name ); } Py::Object old_style_class_func_noargs( void ) { std::cout << "old_style_class_func_noargs Called." << std::endl; return Py::None(); } Py::Object old_style_class_func_varargs( const Py::Tuple &args ) { std::cout << "old_style_class_func_varargs Called with " << args.length() << " normal arguments." << std::endl; return Py::None(); } Py::Object old_style_class_func_keyword( const Py::Tuple &args, const Py::Dict &kwds ) { std::cout << "old_style_class_func_keyword Called with " << args.length() << " normal arguments." << std::endl; Py::List names( kwds.keys() ); std::cout << "and with " << names.length() << " keyword arguments:" << std::endl; for( Py::List::size_type i=0; i< names.length(); i++ ) { Py::String name( names[i] ); std::cout << " " << name << std::endl; } return Py::None(); } }; class simple_module : public Py::ExtensionModule { public: simple_module() : Py::ExtensionModule( "simple" ) // this must be name of the file on disk e.g. simple.so or simple.pyd { old_style_class::init_type(); new_style_class::init_type(); add_varargs_method("old_style_class", &simple_module::factory_old_style_class, "documentation for old_style_class()"); add_keyword_method("func", &simple_module::func, "documentation for func()"); add_keyword_method("make_instance", &simple_module::make_instance, "documentation for make_instance()"); add_keyword_method("decode_test", &simple_module::decode_test, "documentation for decode_test()"); add_keyword_method("encode_test", &simple_module::encode_test, "documentation for encode_test()"); // after initialize the moduleDictionary will exist initialize( "documentation for the simple module" ); Py::Dict d( moduleDictionary() ); d["var"] = Py::String( "var value" ); Py::Object x( new_style_class::type() ); d["new_style_class"] = x; } virtual ~simple_module() {} private: Py::Object decode_test( const Py::Tuple &args, const Py::Dict &kwds ) { Py::Bytes s( args[0] ); return s.decode("utf-8"); } Py::Object encode_test( const Py::Tuple &args, const Py::Dict &kwds ) { Py::String s( args[0] ); return s.encode("utf-8"); } Py::Object func( const Py::Tuple &args, const Py::Dict &kwds ) { std::cout << "func Called with " << args.length() << " normal arguments." << std::endl; Py::List names( kwds.keys() ); std::cout << "and with " << names.length() << " keyword arguments:" << std::endl; for( Py::List::size_type i=0; i< names.length(); i++ ) { Py::String name( names[i] ); std::cout << " " << name << std::endl; } #ifdef PYCXX_DEBUG if( args.length() > 0 ) { Py::Object x( args[0] ); PyObject *x_p = x.ptr(); std::cout << "func( self=0x" << std::hex << reinterpret_cast< unsigned int >( x_p ) << std::dec << " )" << std::endl; Py::PythonClassInstance *instance_wrapper = reinterpret_cast< Py::PythonClassInstance * >( x_p ); new_style_class *instance = static_cast( instance_wrapper->cxx_object ); std::cout << " self->cxx_object=0x" << std::hex << reinterpret_cast< unsigned int >( instance ) << std::dec << std::endl; } bpt(); #endif return Py::None(); } Py::Object make_instance( const Py::Tuple &args, const Py::Dict &kwds ) { std::cout << "make_instance Called with " << args.length() << " normal arguments." << std::endl; Py::List names( kwds.keys() ); std::cout << "and with " << names.length() << " keyword arguments:" << std::endl; for( Py::List::size_type i=0; i< names.length(); i++ ) { Py::String name( names[i] ); std::cout << " " << name << std::endl; } Py::Callable class_type( new_style_class::type() ); Py::PythonClassObject new_style_obj( class_type.apply( args, kwds ) ); return new_style_obj; } Py::Object factory_old_style_class( const Py::Tuple &rargs ) { Py::Object obj = Py::asObject( new old_style_class ); return obj; } }; #if defined( _WIN32 ) #define EXPORT_SYMBOL __declspec( dllexport ) #else #define EXPORT_SYMBOL #endif extern "C" EXPORT_SYMBOL PyObject *PyInit_simple() { #if defined(PY_WIN32_DELAYLOAD_PYTHON_DLL) Py::InitialisePythonIndirectPy::Interface(); #endif static simple_module* simple = new simple_module; return simple->module().ptr(); } #if defined( _WIN32 ) #define EXPORT_SYMBOL __declspec( dllexport ) #else #define EXPORT_SYMBOL #endif // symbol required for the debug version extern "C" EXPORT_SYMBOL PyObject *PyInit_simple_d() { return PyInit_simple(); } pycxx-6.2.5/Demo/Python3/simple2.cxx000644 000771 000000 00000021204 11146616710 017502 0ustar00barrywheel000000 000000 // // Copyright (c) 2008 Barry A. Scott // // // simple2_moduile.cxx // // This module defines a single function. // #ifdef _MSC_VER // disable warning C4786: symbol greater than 255 character, // nessesary to ignore as causes lots of warning #pragma warning(disable: 4786) #endif #include "CXX/Objects.hxx" #include "CXX/Extensions.hxx" #include #include template class EnumString { public: EnumString(); ~EnumString() {} const std::string &toTypeName( T ) { return m_type_name; } const std::string &toString( T value ) { static std::string not_found( "-unknown-" ); EXPLICIT_TYPENAME std::map::iterator it = m_enum_to_string.find( value ); if( it != m_enum_to_string.end() ) return (*it).second; not_found = "-unknown ("; int u1000 = value/1000 % 10; int u100 = value/100 % 10; int u10 = value/10 % 10; int u1 = value % 10; not_found += char( '0' + u1000 ); not_found += char( '0' + u100 ); not_found += char( '0' + u10 ); not_found += char( '0' + u1 ); not_found += ")-"; return not_found; } bool toEnum( const std::string &string, T &value ) { EXPLICIT_TYPENAME std::map::iterator it = m_string_to_enum.find( string ); if( it != m_string_to_enum.end() ) { value = (*it).second; return true; } return false; } EXPLICIT_TYPENAME std::map::iterator begin() { return m_string_to_enum.begin(); } EXPLICIT_TYPENAME std::map::iterator end() { return m_string_to_enum.end(); } private: void add( T value, std::string string ) { m_string_to_enum[string] = value; m_enum_to_string[value] = string; } std::string m_type_name; std::map m_string_to_enum; std::map m_enum_to_string; }; template class pysvn_enum_value : public Py::PythonExtension< EXPLICIT_CLASS pysvn_enum_value > { public: pysvn_enum_value( T _value) : Py::PythonExtension() , m_value( _value ) { } virtual ~pysvn_enum_value() { } virtual int compare( const Py::Object &other ) { if( pysvn_enum_value::check( other ) ) { pysvn_enum_value *other_value = static_cast( other.ptr() ); if( m_value == other_value->m_value ) return 0; if( m_value > other_value->m_value ) return 1; else return -1; } else { std::string msg( "expecting " ); msg += toTypeName( m_value ); msg += " object for compare "; throw Py::AttributeError( msg ); } } virtual Py::Object repr() { std::string s("<"); s += toTypeName( m_value ); s += "."; s += toString( m_value ); s += ">"; return Py::String( s ); } virtual Py::Object str() { return Py::String( toString( m_value ) ); } // need a hash so that the enums can go into a map virtual long hash() { static Py::String type_name( toTypeName( m_value ) ); // use the m_value plus the hash of the type name return long( m_value ) + type_name.hashValue(); } static void init_type(void); public: T m_value; }; //------------------------------------------------------------ template class pysvn_enum : public Py::PythonExtension< EXPLICIT_CLASS pysvn_enum > { public: pysvn_enum() : Py::PythonExtension() { } virtual ~pysvn_enum() { } virtual Py::Object getattr( const char *_name ) { std::string name( _name ); T value; if( name == "__methods__" ) { return Py::List(); } if( name == "__members__" ) { return memberList( static_cast( 0 ) ); } if( toEnum( name, value ) ) { return Py::asObject( new pysvn_enum_value( value ) ); } return this->getattr_methods( _name ); } static void init_type(void); }; template const std::string &toTypeName( T value ) { static EnumString< T > enum_map; return enum_map.toTypeName( value ); } template const std::string &toString( T value ) { static EnumString< T > enum_map; return enum_map.toString( value ); } template bool toEnum( const std::string &string, T &value ) { static EnumString< T > enum_map; return enum_map.toEnum( string, value ); } template Py::List memberList( T value ) { static EnumString< T > enum_map; Py::List members; EXPLICIT_TYPENAME std::map::iterator it = enum_map.begin(); while( it != enum_map.end() ) { members.append( Py::String( (*it).first ) ); ++it; } return members; } typedef enum { xxx_first = 1, xxx_second, xxx_third } xxx_t; template <> EnumString< xxx_t >::EnumString() : m_type_name( "xxx" ) { add( xxx_first, "first" ); add( xxx_second, "second" ); add( xxx_third, "third" ); } template <> void pysvn_enum< xxx_t >::init_type(void) { behaviors().name("xxx"); behaviors().doc("xxx enumeration"); behaviors().supportGetattr(); } template <> void pysvn_enum_value< xxx_t >::init_type(void) { behaviors().name("xxx"); behaviors().doc("xxx value"); behaviors().supportRepr(); behaviors().supportStr(); behaviors().supportHash(); } class cls: public Py::PythonExtension< cls > { public: cls() { } virtual ~cls() { } static void init_type(void) { behaviors().name( "cls" ); behaviors().doc( "documentation for cls class" ); behaviors().supportGetattr(); add_noargs_method( "cls_func_noargs", &cls::cls_func_noargs ); add_varargs_method( "cls_func_varargs", &cls::cls_func_varargs ); add_keyword_method( "cls_func_keyword", &cls::cls_func_keyword ); } // override functions from PythonExtension virtual Py::Object getattr( const char *name ) { return getattr_methods( name ); } Py::Object cls_func_noargs( void ) { std::cout << "cls_func_noargs Called." << std::endl; return Py::None(); } Py::Object cls_func_varargs( const Py::Tuple &args ) { std::cout << "cls_func_varargs Called with " << args.length() << " normal arguments." << std::endl; return Py::None(); } Py::Object cls_func_keyword( const Py::Tuple &args, const Py::Dict &kws ) { std::cout << "cls_func_keyword Called with " << args.length() << " normal arguments." << std::endl; Py::List names( kws.keys() ); std::cout << "and with " << names.length() << " keyword arguments:" << std::endl; for( Py::List::size_type i=0; i< names.length(); i++ ) { Py::String name( names[i] ); std::cout << " " << name << std::endl; } return Py::None(); } }; class simple2_module : public Py::ExtensionModule { public: simple2_module() : Py::ExtensionModule( "simple2" ) // this must be name of the file on disk e.g. simple2.so or simple2.pyd { cls::init_type(); pysvn_enum< xxx_t >::init_type(); pysvn_enum_value< xxx_t >::init_type(); add_varargs_method("cls", &simple2_module::factory_cls, "documentation for cls()"); add_keyword_method("func", &simple2_module::func, "documentation for func()"); // after initialize the moduleDictionary with exist initialize( "documentation for the simple2 module" ); Py::Dict d( moduleDictionary() ); d["xxx"] = Py::asObject( new pysvn_enum< xxx_t >() ); d["var"] = Py::String( "var value" ); } virtual ~simple2_module() {} private: Py::Object func( const Py::Tuple &args, const Py::Dict &kws ) { return Py::None(); } Py::Object factory_cls( const Py::Tuple &rargs ) { return Py::asObject( new cls ); } }; extern "C" PyObject *PyInit_simple2() { #if defined(PY_WIN32_DELAYLOAD_PYTHON_DLL) Py::InitialisePythonIndirectPy::Interface(); #endif static simple2_module* simple2 = new simple2_module; return simple2->module().ptr(); } // symbol required for the debug version extern "C" PyObject *PyInit_simple2_d() { return PyInit_simple2(); } pycxx-6.2.5/Demo/Python3/test_assert.hxx000644 000771 000000 00000005531 11541734230 020476 0ustar00barrywheel000000 000000 // // Copyright (c) 2008-2009 Barry A. Scott // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF // CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH // DAMAGE. // // test_assert.hxx // class TestError { public: TestError( const std::string &description ) : m_description( description ) {} ~TestError() {} std::string m_description; }; template static void test_assert_scaler( const char *description, const char *type, T benchmark, T value ) { std::ostringstream full_description; full_description << description << ": " << type << " benchmark=" << benchmark << " " << type << " value=" << value; if( benchmark != value ) { throw TestError( full_description.str() ); } else { std::cout << "PASSED: " << full_description.str() << std::endl; } } static void test_assert( const char *description, bool benchmark, bool value ) { test_assert_scaler( description, "bool", benchmark, value ); } static void test_assert( const char *description, long benchmark, long value ) { test_assert_scaler( description, "long", benchmark, value ); } static void test_assert( const char *description, int benchmark, int value ) { test_assert_scaler( description, "int", benchmark, value ); } static void test_assert( const char *description, size_t benchmark, size_t value ) { test_assert_scaler( description, "size_t", benchmark, value ); } static void test_assert( const char *description, int benchmark, size_t value ) { test_assert_scaler( description, "size_t", size_t( benchmark ), value ); } static void test_assert( const char *description, double benchmark, double value ) { test_assert_scaler( description, "float", benchmark, value ); } static void test_assert( const char *description, const std::string &benchmark, const std::string &value ) { test_assert_scaler( description, "std::string", benchmark, value ); } static void test_assert( const char *description, const Py::Object &benchmark, const Py::Object &value ) { test_assert_scaler( description, "Py::Object", benchmark, value ); } pycxx-6.2.5/Demo/Python3/test_example.py000644 000771 000000 00000004257 11146616710 020460 0ustar00barrywheel000000 000000 #----------------------------------------------------------------------------- # # Copyright (c) 1998 - 2007, The Regents of the University of California # Produced at the Lawrence Livermore National Laboratory # All rights reserved. # # This file is part of PyCXX. For details,see http:#cxx.sourceforge.net/. The # full copyright notice is contained in the file COPYRIGHT located at the root # of the PyCXX distribution. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # - Redistributions of source code must retain the above copyright notice, # this list of conditions and the disclaimer below. # - Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the disclaimer (as noted below) in the # documentation and/or materials provided with the distribution. # - Neither the name of the UC/LLNL nor the names of its contributors may be # used to endorse or promote products derived from this software without # specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF # CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH # DAMAGE. # #----------------------------------------------------------------------------- import sys sys.path.insert( 0, 'pyds%d%d' % (sys.version_info[0], sys.version_info[1]) ) import example example.test() pycxx-6.2.5/Demo/Python3/test_pycxx_iter.py000644 000771 000000 00000000473 11146616710 021217 0ustar00barrywheel000000 000000 import sys sys.path.insert( 0, 'pyds%d%d' % (sys.version_info[0], sys.version_info[1]) ) import pycxx_iter it = pycxx_iter.IterT( 5, 7 ) for i in it: print( i, it ) print( "refcount of it:", sys.getrefcount( it ) ) for i in it.reversed(): print( i ) print( "refcount of it:", sys.getrefcount( it ) ) pycxx-6.2.5/Demo/Python3/test_simple.py000644 000771 000000 00000003347 11347772667 020336 0ustar00barrywheel000000 000000 import simple print( '--- module func ---' ) simple.func() simple.func( 4, 5 ) simple.func( 4, 5, name=6, value=7 ) print( '--- old_style_class func ---' ) old_style_class = simple.old_style_class() old_style_class.old_style_class_func_noargs() old_style_class.old_style_class_func_varargs() old_style_class.old_style_class_func_varargs( 4 ) old_style_class.old_style_class_func_keyword() old_style_class.old_style_class_func_keyword( name=6, value=7 ) old_style_class.old_style_class_func_keyword( 4, 5 ) old_style_class.old_style_class_func_keyword( 4, 5, name=6, value=7 ) print( '--- Derived func ---' ) class Derived(simple.new_style_class): def __init__( self ): simple.new_style_class.__init__( self ) def derived_func( self ): print( 'derived_func' ) super().func_noargs() def func_noargs( self ): print( 'derived func_noargs' ) d = Derived() print( dir( d ) ) d.derived_func() d.func_noargs() d.func_varargs() d.func_varargs( 4 ) d.func_keyword() d.func_keyword( name=6, value=7 ) d.func_keyword( 4, 5 ) d.func_keyword( 4, 5, name=6, value=7 ) print( d.value ) d.value = "a string" print( d.value ) d.new_var = 99 print( '--- new_style_class func ---' ) new_style_class = simple.new_style_class() print( dir( new_style_class ) ) new_style_class.func_noargs() new_style_class.func_varargs() new_style_class.func_varargs( 4 ) new_style_class.func_keyword() new_style_class.func_keyword( name=6, value=7 ) new_style_class.func_keyword( 4, 5 ) new_style_class.func_keyword( 4, 5, name=6, value=7 ) try: new_style_class.func_noargs_raise_exception() print( 'Error: did not raised RuntimeError' ) sys.exit( 1 ) except RuntimeError as e: print( 'Raised %r' % (str(e),) ) new_style_class = None pycxx-6.2.5/Demo/Python3/test_simple2.py000644 000771 000000 00000000216 11146066410 020363 0ustar00barrywheel000000 000000 import simple2 m = { simple2.xxx.first: 1, simple2.xxx.second: 2, simple2.xxx.third: 3 } v = m[ simple2.xxx.second ] print( v ) pycxx-6.2.5/Demo/Python2/example.cxx000644 000771 000000 00000044716 11367330334 017576 0ustar00barrywheel000000 000000 //----------------------------------------------------------------------------- // // Copyright (c) 1998 - 2007, The Regents of the University of California // Produced at the Lawrence Livermore National Laboratory // All rights reserved. // // This file is part of PyCXX. For details, see http://cxx.sourceforge.net. The // full copyright notice is contained in the file COPYRIGHT located at the root // of the PyCXX distribution. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // - Redistributions of source code must retain the above copyright notice, // this list of conditions and the disclaimer below. // - Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the disclaimer (as noted below) in the // documentation and/or materials provided with the distribution. // - Neither the name of the UC/LLNL nor the names of its contributors may be // used to endorse or promote products derived from this software without // specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF // CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH // DAMAGE. // //----------------------------------------------------------------------------- #ifdef _MSC_VER // disable warning C4786: symbol greater than 255 character, // nessesary to ignore as causes lots of warning #pragma warning(disable: 4786) #endif #include "CXX/Objects.hxx" #include "CXX/Extensions.hxx" #include #include "range.hxx" // Extension object extern std::string test_extension_object(); #include static std::string test_String() { Py::String s("hello"); Py::Char blank = ' '; Py::String r1("world in brief", 5); s = s + blank + r1; s = s * 2; if(std::string(s) != "hello worldhello world") { return "failed (1) '" + std::string(s) + "'"; } // test conversion std::string w = static_cast(s); std::string w2 = (std::string) s; if(w != w2) { return "failed (2)"; } Py::String r2("12345 789"); Py::Char c6 = r2[5]; if(c6 != blank) { std::cout << "|" << c6 << "|" << std::endl; return "failed (3)"; } Py::Char c7 = r2.front(); Py::Char c8 = r2.back(); return "ok"; } static std::string test_boolean() { bool passed = true; Py::Object o; Py::Boolean pb1; Py::Boolean pb2; bool b1; o = Py::True(); if( o.isTrue() ) { std::cout << "OK: T1: True" << std::endl; } else { std::cout << "Bad: T1: False" << std::endl; passed = false; } pb1 = o; if( pb1 ) { std::cout << "OK: T2: True" << std::endl; } else { std::cout << "Bad: T2: False" << std::endl; passed = false; } b1 = pb1; if( b1 ) { std::cout << "OK: T3: True" << std::endl; } else { std::cout << "Bad: T3: False" << std::endl; passed = false; } pb2 = pb1; if( pb2 ) { std::cout << "OK: T4: True" << std::endl; } else { std::cout << "Bad: T4: False" << std::endl; passed = false; } pb2 = true; if( pb2 ) { std::cout << "OK: T5: True" << std::endl; } else { std::cout << "Bad: T5: False" << std::endl; passed = false; } o = Py::False(); if( o.isTrue() ) { std::cout << "Bad: F1: True" << std::endl; passed = false; } else { std::cout << "OK: F1: False" << std::endl; } pb1 = o; if( pb1 ) { std::cout << "Bad: F2: True" << std::endl; passed = false; } else { std::cout << "OK: F2: False" << std::endl; } b1 = pb1; if( b1 ) { std::cout << "Bad: F3: True" << std::endl; passed = false; } else { std::cout << "OK: F3: False" << std::endl; } pb2 = pb1; if( pb2 ) { std::cout << "Bad: F4: True" << std::endl; passed = false; } else { std::cout << "OK: F4: False" << std::endl; } pb2 = false; if( pb2 ) { std::cout << "Bad: F5: True" << std::endl; passed = false; } else { std::cout << "OK: F5: False" << std::endl; } if( passed ) return "ok"; else return "failed"; } static std::string test_numbers() { // test the basic numerical classes Py::Int i; Py::Int j(2); Py::Int k = Py::Int(3); if (! (j < k)) return "failed (1)"; if (! (j == j)) return "failed (2)" ; if (! (j != k)) return "failed (3)"; if (! (j <= k)) return "failed (4)"; if (! (k >= j)) return "failed (5)"; if (! (k > j)) return "failed (6)"; if (! (j <= j)) return "failed (7)"; if (! (j >= Py::Int(2))) return "failed (8)"; i = 2; Py::Float a; a = 3 + i; //5.0 Py::Float b(4.0); a = (1.0 + 2*a + (b*3.0)/2.0 + k)/Py::Float(5); // 4.0 i = a - 1.0; // 3 if(i != k) { return "failed 9"; } return "ok"; } static std::string test_List_iterators (const Py::List& x, Py::List& y) { std::vector v; Py::Sequence::iterator j; int k = 0; for(Py::Sequence::const_iterator i = x.begin(); i != x.end(); ++i) { if ((*i).isList()) { ++k; } } if(k!=1) return "failed List iterators (1)"; k = 0; for(j = y.begin(); j != y.end(); ++j) { *j = Py::Int(k++); v.push_back (*j); } k = 0; for(j = y.begin(); j != y.end(); j++) { if(*j != Py::Int(k)) return "failed List iterators (2)"; if(v[k] != Py::Int(k)) return "failed List iterators (3)"; ++k; } Py::String o1("Howdy"); Py::Int o2(1); int caught_it = 0; try { o2 = o1; } catch (Py::Exception& e) { caught_it = 1; e.clear(); } if(!caught_it) return "failed exception catch (4)."; return "ok"; } static Py::List test_List_references (Py::List& x) { Py::List y; for(Py::List::size_type i=0; i < x.length(); ++i) { if (x[i].isList()) { y = x[i]; } } return y; } static std::string test_List() { // test the Py::List class Py::List a; Py::List ans, aux; aux.append(Py::Int(3)); aux.append(Py::Float(6.0)); Py::Object b; Py::Int i(3); Py::Float x(6.0); Py::Float c(10.0), d(20.0); a.append(i); a.append(x); a.append(Py::Float(0.0)); b = a[0]; a[2] = b; a.append(c+d); a.append(aux); // a is now [3, 6.0, 3, 30.0, aux] ans.append(Py::Int(3)); ans.append(Py::Float(6.0)); ans.append(Py::Int(3)); ans.append(Py::Float(30.0)); ans.append(aux); Py::List::iterator l1, l2; for(l1= a.begin(), l2 = ans.begin(); l1 != a.end() && l2 != ans.end(); ++l1, ++l2) { if(*l1 != *l2) return "failed 1" + a.as_string(); } if (test_List_references (a)!= aux) { return "failed 2" + test_List_references(a).as_string(); } return test_List_iterators(ans, a); } static std::string test_Dict() { // test the Dict class Py::Dict a,b; Py::List v; Py::String s("two"); a["one"] = Py::Int(1); a[s] = Py::Int(2); a["three"] = Py::Int(3); if(Py::Int(a["one"]) != Py::Int(1)) return "failed 1a " + a.as_string(); if(Py::Int(a[s]) != Py::Int(2)) return "failed 1b " + a.as_string(); v = a.values(); #if 0 std::sort(v.begin(), v.end()); for(int k = 1; k < 4; ++k) { if(v[k-1] != Py::Int(k)) return "failed 2 " + v.as_string(); } #endif b = a; b.clear(); if(b.keys().length() != 0) { return "failed 3 " + b.as_string(); } const Py::Dict c; for (Py::Dict::const_iterator it = c.begin(); it != c.end(); ++it) { } return "ok"; } static std::string test_Tuple() { // test the Tuple class Py::Tuple a(3); Py::Tuple t; Py::Float f1(1.0), f2(2.0), f3(3.0); a[0] = f1; // should be ok since no other reference owned a[1] = f2; a[2] = f3; Py::Tuple b(a); int k = 0; for(Py::Tuple::iterator i = b.begin(); i != b.end(); ++i) { if(*i != Py::Float(++k)) return "failed 1 " + b.as_string(); } t = a; try { t[0] = Py::Int(1); // should fail, tuple has multiple references return "failed 2"; } catch (Py::Exception& e) { e.clear(); } Py::TupleN t0; Py::TupleN t1( Py::Int( 1 ) ); Py::TupleN t2( Py::Int( 1 ), Py::Int( 2 ) ); Py::TupleN t3( Py::Int( 1 ), Py::Int( 2 ), Py::Int( 3 ) ); Py::TupleN t4( Py::Int( 1 ), Py::Int( 2 ), Py::Int( 3 ), Py::Int( 4 ) ); Py::TupleN t5( Py::Int( 1 ), Py::Int( 2 ), Py::Int( 3 ), Py::Int( 4 ), Py::Int( 5 ) ); Py::TupleN t6( Py::Int( 1 ), Py::Int( 2 ), Py::Int( 3 ), Py::Int( 4 ), Py::Int( 5 ), Py::Int( 6 ) ); Py::TupleN t7( Py::Int( 1 ), Py::Int( 2 ), Py::Int( 3 ), Py::Int( 4 ), Py::Int( 5 ), Py::Int( 6 ), Py::Int( 7 ) ); Py::TupleN t8( Py::Int( 1 ), Py::Int( 2 ), Py::Int( 3 ), Py::Int( 4 ), Py::Int( 5 ), Py::Int( 6 ), Py::Int( 7 ), Py::Int( 8 ) ); Py::TupleN t9( Py::Int( 1 ), Py::Int( 2 ), Py::Int( 3 ), Py::Int( 4 ), Py::Int( 5 ), Py::Int( 6 ), Py::Int( 7 ), Py::Int( 8 ), Py::Int( 9 ) ); return "ok"; } static std::string test_STL() { int ans1; Py::List w; Py::List wans; wans.append(Py::Int(1)); wans.append(Py::Int(1)); wans.append(Py::Int(2)); wans.append(Py::Int(3)); wans.append(Py::Int(4)); wans.append(Py::Int(5)); w.append(Py::Int(5)); w.append(Py::Int(1)); w.append(Py::Int(4)); w.append(Py::Int(2)); w.append(Py::Int(3)); w.append(Py::Int(1)); ans1 = std::count(w.begin(), w.end(), Py::Float(1.0)); if (ans1 != 2) { return "failed count test"; } #if 0 std::sort(w.begin(), w.end()); if (w != wans) { return "failed sort test"; } #endif Py::Dict d; Py::String s1("blah"); Py::String s2("gorf"); d[ "one" ] = s1; d[ "two" ] = s1; d[ "three" ] = s2; d[ "four" ] = s2; Py::Dict::iterator it = d.begin(); for( ; it != d.end(); ++it ) { Py::Dict::value_type vt( *it ); Py::String rs = vt.second.repr(); std::string ls = rs.operator std::string(); std::cout << "dict value " << ls.c_str() << std::endl; } return "ok"; } void debug_check_ref_queue() { #ifdef Py_TRACE_REFS // create an element to find the queue Py::Int list_element; PyObject *p_slow = list_element.ptr(); PyObject *p_fast = p_slow; do { assert( p_slow->_ob_next->_ob_prev == p_slow ); assert( p_slow->_ob_prev->_ob_next == p_slow ); p_slow = p_slow->_ob_next; p_fast = p_slow->_ob_next->_ob_next; assert( p_slow != p_fast ); } while( p_slow != list_element.ptr() ); #endif } class example_module : public Py::ExtensionModule { public: example_module() : Py::ExtensionModule( "example" ) { range::init_type(); add_varargs_method("string", &example_module::ex_string, "string( s ) = return string"); add_varargs_method("sum", &example_module::ex_sum, "sum(arglist) = sum of arguments"); add_varargs_method("test", &example_module::ex_test, "test(arglist) runs a test suite"); add_varargs_method("range", &example_module::new_r, "range(start,stop,stride)"); add_keyword_method("kw", &example_module::ex_keyword, "kw()"); initialize( "documentation for the example module" ); Py::Dict d( moduleDictionary() ); Py::Object b(Py::asObject(new range(1,10,2))); d["a_constant"] = b.getAttr("c"); } virtual ~example_module() {} private: Py::Object ex_keyword( const Py::Tuple &args, const Py::Dict &kws ) { std::cout << "Called with " << args.length() << " normal arguments." << std::endl; Py::List names( kws.keys() ); std::cout << "and with " << names.length() << " keyword arguments:" << std::endl; for( Py::List::size_type i=0; i< names.length(); i++ ) { Py::String name( names[i] ); std::cout << " " << name << std::endl; } return Py::Int(0); } Py::Object new_r (const Py::Tuple &rargs) { if (rargs.length() < 2 || rargs.length() > 3) { throw Py::RuntimeError("Incorrect # of args to range(start,stop [,step])."); } Py::Int start(rargs[0]); Py::Int stop(rargs[1]); Py::Int step(1); if (rargs.length() == 3) { step = rargs[2]; } if (long(start) > long(stop) + 1 || long(step) == 0) { throw Py::RuntimeError("Bad arguments to range(start,stop [,step])."); } return Py::asObject(new range(start, stop, step)); } Py::Object ex_string (const Py::Tuple &a) { std::cout << "ex_std::string: s1 is first arg" << std::endl; Py::String s1( a[0] ); std::cout << "ex_string: s1.isString() " << s1.isString() << std::endl; std::cout << "ex_string: s1.isUnicode() " << s1.isUnicode() << std::endl; std::cout << "ex_string: s1.size() " << s1.size() << std::endl; if( s1.isUnicode() ) { std::cout << "ex_string: s2 is s1.encode( utf-8 )" << std::endl; Py::String s2( s1.encode( "utf-8" ) ); std::cout << "ex_string: s2.isString() " << s2.isString() << std::endl; std::cout << "ex_string: s2.isUnicode() " << s2.isUnicode() << std::endl; std::cout << "ex_string: s2.size() " << s2.size() << std::endl; return s2; } else { std::cout << "ex_string: s2 is s1.decode( utf-8 )" << std::endl; Py::String s2( s1.decode( "utf-8" ) ); std::cout << "ex_string: s2.isString() " << s2.isString() << std::endl; std::cout << "ex_string: s2.isUnicode() " << s2.isUnicode() << std::endl; std::cout << "ex_string: s2.size() " << s2.size() << std::endl; return s2; } } Py::Object ex_sum (const Py::Tuple &a) { // this is just to test the function verify_length: try { a.verify_length(0); std::cout << "I see that you refuse to give me any work to do." << std::endl; } catch (Py::Exception& e) { e.clear(); std::cout << "I will now add up your elements, oh great one." << std::endl; } Py::Float f(0.0); for( Py::Sequence::size_type i = 0; i < a.length(); i++ ) { Py::Float g (a[i]); f = f + g; } return f; } Py::Object ex_test( const Py::Tuple &a) { debug_check_ref_queue(); std::cout << "Example Test starting" << std::endl; try { PyObject *p = NULL; std::cout << "Trying to convert a NULL to an Py::Int" << std::endl; Py::Int k( p ); std::cout << "Failed to raise error" << std::endl; } catch (Py::TypeError& e) { std::cout << "Correctly caught " << Py::type(e) << std::endl; std::cout << " Py::Exception value: " << Py::value(e) << std::endl; std::cout << " Py::Exception traceback: " << Py::trace(e) << std::endl; e.clear(); } try { Py::String s("this should fail"); PyObject *p = s.ptr(); std::cout << "Trying to convert a Py::String to an Py::Int" << std::endl; Py::Int k( p ); std::cout << "Failed to raise error" << std::endl; } catch (Py::TypeError& e) { std::cout << "Correctly caught " << Py::type(e) << std::endl; std::cout << " Py::Exception value: " << Py::value(e) << std::endl; std::cout << " Py::Exception traceback: " << Py::trace(e) << std::endl; e.clear(); } debug_check_ref_queue(); std::string result = test_boolean(); std::cout << "Py::Boolean: " << result << std::endl; debug_check_ref_queue(); std::cout << "Numbers: " << test_numbers() << std::endl; debug_check_ref_queue(); std::cout << "Py::String: " << test_String() << std::endl; debug_check_ref_queue(); std::cout << "Py::List: " << test_List() << std::endl; debug_check_ref_queue(); std::cout << "Py::Dict: " << test_Dict() << std::endl; debug_check_ref_queue(); std::cout << "Py::Tuple: " << test_Tuple() << std::endl; debug_check_ref_queue(); std::cout << "STL test: " << test_STL() << std::endl; debug_check_ref_queue(); std::cout << "Extension object test: " << test_extension_object() << std::endl; debug_check_ref_queue(); Py::List b(a); Py::Tuple c(b); if( c != a) { std::cout << "Py::Tuple/list conversion failed.\n"; } Py::Module m("sys"); Py::Object s = m.getAttr("stdout"); Py::Object nun; nun = PyObject_CallMethod(s.ptr(), "write", "s", "Module test ok.\n"); return Py::None(); } }; #if defined( _WIN32 ) #define EXPORT_SYMBOL __declspec( dllexport ) #else #define EXPORT_SYMBOL #endif extern "C" EXPORT_SYMBOL void initexample() { #if defined(PY_WIN32_DELAYLOAD_PYTHON_DLL) Py::InitialisePythonIndirectPy::Interface(); #endif static example_module* example = new example_module; } // symbol required for the debug version extern "C" EXPORT_SYMBOL void initexample_d() { initexample(); } pycxx-6.2.5/Demo/Python2/example.def000644 000771 000000 00000000026 11146616710 017514 0ustar00barrywheel000000 000000 EXPORTS initexample pycxx-6.2.5/Demo/Python2/pycxx_iter.cxx000644 000771 000000 00000002561 11367330334 020331 0ustar00barrywheel000000 000000 #include "pycxx_iter.hxx" #include "CXX/Objects.hxx" void IterT::init_type() { behaviors().name("IterT"); behaviors().doc("IterT(ini_count)"); // you must have overwritten the virtual functions // Py::Object iter() and Py::Object iternext() behaviors().supportIter(); // set entries in the Type Table behaviors().supportRepr(); add_varargs_method("reversed",&IterT::reversed,"reversed()"); } class MyIterModule : public Py::ExtensionModule { public: MyIterModule() : Py::ExtensionModule("pycxx_iter") { IterT::init_type(); add_varargs_method("IterT",&MyIterModule::new_IterT,"IterT(from,last)"); initialize("MyIterModule documentation"); // register with Python } virtual ~MyIterModule() {} private: Py::Object new_IterT(const Py::Tuple& args) { if (args.length() != 2) { throw Py::RuntimeError("Incorrect # of args to IterT(from,to)."); } return Py::asObject(new IterT(Py::Int(args[0]),Py::Int(args[1]))); } }; #if defined( _WIN32 ) #define EXPORT_SYMBOL __declspec( dllexport ) #else #define EXPORT_SYMBOL #endif extern "C" EXPORT_SYMBOL void initpycxx_iter() { // the following constructor call registers our extension module // with the Python runtime system static MyIterModule* IterTest = new MyIterModule; } pycxx-6.2.5/Demo/Python2/pycxx_iter.hxx000644 000771 000000 00000003612 11146616710 020334 0ustar00barrywheel000000 000000 #include "CXX/Extensions.hxx" #include #include #include class IterT : public Py::PythonExtension { int from, count, last; int fwd_iter; bool do_it_reversed; public: static void init_type(void); // announce properties and methods IterT(int _from, int _last) : from(_from) , last(_last) , fwd_iter(0) , do_it_reversed(false) {} Py::Object repr() { std::string s; std::ostringstream s_out; s_out << "IterT count(" << count << ")"; return Py::String(s_out.str()); } Py::Object reversed(const Py::Tuple&) { do_it_reversed= true; // indicate backward iteration return Py::Object(this,false); // increment the refcount } Py::Object iter() { if( do_it_reversed ) { fwd_iter = -1; do_it_reversed=false; } else fwd_iter = 1; // indicate forward iteration return Py::Object(this,false); // increment the refcount } PyObject* iternext() { int ct; if( ! fwd_iter ) return NULL; // signal StopIteration if( fwd_iter > 0 ) { if( fwd_iter == 1 ) { ct = from; count = from+1; fwd_iter=2; } else if( count <= last ) ct= count++; else return NULL; // signal StopIteration } else if( fwd_iter == -1 ) { ct = last; count = last-1; fwd_iter=-2; } else if( count >= from ) ct= count--; else return NULL; // signal StopIteration Py::Int Result(ct); Result.increment_reference_count(); return Result.ptr(); } }; pycxx-6.2.5/Demo/Python2/python.cxx000644 000771 000000 00000004776 11146616710 017466 0ustar00barrywheel000000 000000 //----------------------------------------------------------------------------- // // Copyright (c) 1998 - 2007, The Regents of the University of California // Produced at the Lawrence Livermore National Laboratory // All rights reserved. // // This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The // full copyright notice is contained in the file COPYRIGHT located at the root // of the PyCXX distribution. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // - Redistributions of source code must retain the above copyright notice, // this list of conditions and the disclaimer below. // - Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the disclaimer (as noted below) in the // documentation and/or materials provided with the distribution. // - Neither the name of the UC/LLNL nor the names of its contributors may be // used to endorse or promote products derived from this software without // specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF // CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH // DAMAGE. // //----------------------------------------------------------------------------- /* Minimal main program -- everything is loaded from the library */ #include "CXX/WrapPython.h" #include extern "C" int Py_Main(int argc, char** argv); extern "C" void initexample(); extern "C" void Py_Initialize(); int main(int argc, char** argv) { std::cout << "Greetings. Type from example import *; test()" << std::endl; Py_Initialize(); initexample(); return Py_Main(argc, argv); } pycxx-6.2.5/Demo/Python2/range.cxx000755 000771 000000 00000007607 11146616710 017240 0ustar00barrywheel000000 000000 //----------------------------------------------------------------------------- // // Copyright (c) 1998 - 2007, The Regents of the University of California // Produced at the Lawrence Livermore National Laboratory // All rights reserved. // // This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The // full copyright notice is contained in the file COPYRIGHT located at the root // of the PyCXX distribution. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // - Redistributions of source code must retain the above copyright notice, // this list of conditions and the disclaimer below. // - Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the disclaimer (as noted below) in the // documentation and/or materials provided with the distribution. // - Neither the name of the UC/LLNL nor the names of its contributors may be // used to endorse or promote products derived from this software without // specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF // CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH // DAMAGE. // //----------------------------------------------------------------------------- #ifdef _MSC_VER // disable warning C4786: symbol greater than 255 character, // nessesary to ignore as causes lots of warning #pragma warning(disable: 4786) #endif #include "range.hxx" // Connect range objects to Python Py::Object range::repr() { return Py::String(asString()); } int range::sequence_length() { return length(); } Py::Object range::sequence_item(Py_ssize_t i) { return Py::Int(item(i)); } Py::Object range::sequence_concat( const Py::Object &j ) { Py::Int k(j); return Py::asObject(extend(int(k))); } Py::Object range::sequence_slice(Py_ssize_t i, Py_ssize_t j) { return Py::asObject(slice(i,j)); } Py::Object range::getattr( const char *name ) { if(std::string(name) == "c") return Py::Float(300.0); if(std::string(name) == "start") return Py::Int(start); return getattr_methods( name ); } // "regular" methods... Py::Object range::amethod( const Py::Tuple &t ) { t.verify_length(1); Py::List result; result.append(Py::Object(this)); result.append(t[0]); return result; } Py::Object range::value( const Py::Tuple &t ) { return c_value(t); } Py::Object range::assign( const Py::Tuple &t ) { t.verify_length(2); Py::Tuple t1(t[0]); // subscripts Py::Object o2(t[1]); // rhs; c_assign (t1, o2); return Py::Nothing(); } void range::init_type() { behaviors().name("range"); behaviors().doc("range objects: start, stop, step"); behaviors().supportRepr(); behaviors().supportGetattr(); behaviors().supportSequenceType(); add_varargs_method("amethod", &range::amethod, "demonstrate how to document amethod"); add_varargs_method("assign", &range::assign); add_varargs_method("value", &range::value); add_varargs_method("reference_count", &range::reference_count); } pycxx-6.2.5/Demo/Python2/range.hxx000755 000771 000000 00000012723 11146616710 017240 0ustar00barrywheel000000 000000 //----------------------------------------------------------------------------- // // Copyright (c) 1998 - 2007, The Regents of the University of California // Produced at the Lawrence Livermore National Laboratory // All rights reserved. // // This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The // full copyright notice is contained in the file COPYRIGHT located at the root // of the PyCXX distribution. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // - Redistributions of source code must retain the above copyright notice, // this list of conditions and the disclaimer below. // - Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the disclaimer (as noted below) in the // documentation and/or materials provided with the distribution. // - Neither the name of the UC/LLNL nor the names of its contributors may be // used to endorse or promote products derived from this software without // specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF // CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH // DAMAGE. // //----------------------------------------------------------------------------- #ifndef __r__h #define __r__h #include "CXX/Extensions.hxx" #include STR_STREAM // Making an extension object class range: public Py::PythonExtension { public: long start; long stop; long step; range(long start_, long stop_, long step_ = 1L) { start = start_; stop = stop_; step = step_; std::cout << "range object created " << this << std::endl; } virtual ~range() { std::cout << "range object destroyed " << this << std::endl; } static void init_type(void); long length() const { return (stop - start + 1)/step; } long item(int i) const { if( i >= length() ) // this exception stops a Python for loop over range. throw Py::IndexError("index too large"); return start + i * step; } range* slice(int i, int j) const { int first = start + i * step; int last = start + j * step; return new range(first, last, step); } range* extend(int k) const { return new range(start, stop + k, step); } std::string asString() const { std::OSTRSTREAM s; s << "range(" << start << ", " << stop << ", " << step << ")" << std::ends; return std::string(s.str()); } // override functions from PythonExtension virtual Py::Object repr(); virtual Py::Object getattr( const char *name ); virtual int sequence_length(); virtual Py::Object sequence_item( Py_ssize_t i ); virtual Py::Object sequence_concat( const Py::Object &j ); virtual Py::Object sequence_slice( Py_ssize_t i, Py_ssize_t j ); // define python methods of this object Py::Object amethod (const Py::Tuple& args); Py::Object value (const Py::Tuple& args); Py::Object assign (const Py::Tuple& args); Py::Object reference_count (const Py::Tuple& args) { return Py::Int(this->ob_refcnt); } Py::Object c_value(const Py::Tuple&) const { Py::List result; for(int i = start; i <= stop; i += step) { result.append(Py::Int(i)); } return result; } void c_assign(const Py::Tuple&, const Py::Object& rhs) { Py::Tuple w(rhs); w.verify_length(3); start = long(Py::Int(w[0])); stop = long(Py::Int(w[1])); step = long(Py::Int(w[2])); } }; class RangeSequence: public Py::SeqBase { public: explicit RangeSequence (PyObject *pyob, bool owned = false): Py::SeqBase(pyob, owned) { validate(); } explicit RangeSequence(int start, int stop, int step = 1) { set (new range(start, stop, step), true); } RangeSequence(const RangeSequence& other): Py::SeqBase(*other) { validate(); } RangeSequence& operator= (const Py::Object& rhs) { return (*this = *rhs); } RangeSequence& operator= (PyObject* rhsp) { if(ptr() == rhsp) return *this; set(rhsp); return *this; } virtual bool accepts(PyObject *pyob) const { return pyob && range::check(pyob); } Py::Object value(const Py::Tuple& t) const { return static_cast(ptr())->c_value(t); } void assign(const Py::Tuple& t, const Py::Object& rhs) { static_cast(ptr())->c_assign(t, rhs); } }; #endif pycxx-6.2.5/Demo/Python2/rangetest.cxx000755 000771 000000 00000010737 11347431443 020137 0ustar00barrywheel000000 000000 //----------------------------------------------------------------------------- // // Copyright (c) 1998 - 2007, The Regents of the University of California // Produced at the Lawrence Livermore National Laboratory // All rights reserved. // // This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The // full copyright notice is contained in the file COPYRIGHT located at the root // of the PyCXX distribution. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // - Redistributions of source code must retain the above copyright notice, // this list of conditions and the disclaimer below. // - Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the disclaimer (as noted below) in the // documentation and/or materials provided with the distribution. // - Neither the name of the UC/LLNL nor the names of its contributors may be // used to endorse or promote products derived from this software without // specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF // CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH // DAMAGE. // //----------------------------------------------------------------------------- #ifdef _MSC_VER // disable warning C4786: symbol greater than 255 character, // nessesary to ignore as causes lots of warning #pragma warning(disable: 4786) #endif #include "CXX/Extensions.hxx" #include "range.hxx" // This test also illustrates using the Py namespace explicitly extern void debug_check_ref_queue(); std::string test_extension_object() { debug_check_ref_queue(); Py::Tuple a; // just something that isn't an range... Py::ExtensionObject r1( new range(1, 20, 3) ); if(range::check(a)) std::cout << "range::check failed (1)."; if(!range::check(r1)) return "r::check failed (2)."; debug_check_ref_queue(); RangeSequence r2(1, 10, 2); if(r2[1] != Py::Int(3)) return "RangeSequence check failed. "; debug_check_ref_queue(); // calling an extension object method using getattr Py::Callable w(r2.getAttr("amethod")); Py::Tuple args(1); Py::Int j(3); args[0]=j; Py::List answer(w.apply(args)); if(answer[0] != r2) return ("Extension object test failed (1)"); if(answer[1] != args[0]) return ("Extension object test failed (2)"); // calling an extension object method using callMemberFunction Py::List answer2( r2.callMemberFunction( "amethod", args ) ); if(answer2[0] != r2) return ("Extension object test failed (3)"); if(answer2[1] != args[0]) return ("Extension object test failed (4)"); debug_check_ref_queue(); Py::Tuple nv(3); nv[0] = Py::Int(1); nv[1] = Py::Int(20); nv[2] = Py::Int(3); Py::Tuple unused; Py::List r2value; r2.assign(unused, nv); r2value = r2.value(unused); if(r2value[1] != Py::Int(4)) return("Extension object test failed (5)"); debug_check_ref_queue(); // repeat using getattr w = r2.getAttr("assign"); Py::Tuple the_arguments(2); the_arguments[0] = unused; the_arguments[1] = nv; w.apply(the_arguments); debug_check_ref_queue(); w = r2.getAttr("value"); Py::Tuple one_arg(1); one_arg[0] = unused; r2value = w.apply(one_arg); if(r2value[1] != Py::Int(4)) return("Extension object test failed. (6)"); debug_check_ref_queue(); { Py::ExtensionObject rheap( new range(1, 10, 2) ); debug_check_ref_queue(); // delete rheap } debug_check_ref_queue(); return "ok."; } pycxx-6.2.5/Demo/Python2/setup.py000644 000771 000000 00000006311 11214645533 017117 0ustar00barrywheel000000 000000 #----------------------------------------------------------------------------- # # Copyright (c) 1998 - 2007, The Regents of the University of California # Produced at the Lawrence Livermore National Laboratory # All rights reserved. # # This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The # full copyright notice is contained in the file COPYRIGHT located at the root # of the PyCXX distribution. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # - Redistributions of source code must retain the above copyright notice, # this list of conditions and the disclaimer below. # - Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the disclaimer (as noted below) in the # documentation and/or materials provided with the distribution. # - Neither the name of the UC/LLNL nor the names of its contributors may be # used to endorse or promote products derived from this software without # specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF # CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH # DAMAGE. # #----------------------------------------------------------------------------- import os, sys from distutils.core import setup, Extension support_dir = os.path.normpath( os.path.join( sys.prefix, 'share', 'python%d.%d' % (sys.version_info[0],sys.version_info[1]), 'CXX') ) if os.name == 'posix': CXX_libraries = ['stdc++','m'] else: CXX_libraries = [] setup (name = "CXXDemo", version = "5.1", maintainer = "Barry Scott", maintainer_email = "barry-scott@users.sourceforge.net", description = "Demo of facility for extending Python with C++", url = "http://cxx.sourceforge.net", packages = ['CXX'], package_dir = {'CXX': '.'}, ext_modules = [ Extension('CXX.example', sources = ['example.cxx', 'range.cxx', 'rangetest.cxx', os.path.join(support_dir,'cxxsupport.cxx'), os.path.join(support_dir,'cxx_extensions.cxx'), os.path.join(support_dir,'IndirectPythonInterface.cxx'), os.path.join(support_dir,'cxxextensions.c') ], ) ] ) pycxx-6.2.5/Demo/Python2/simple.cxx000644 000771 000000 00000024010 11523511652 017413 0ustar00barrywheel000000 000000 // // Copyright (c) 2008-2010 Barry A. Scott // // // simple_moduile.cxx // // This module defines a single function. // #ifdef _MSC_VER // disable warning C4786: symbol greater than 255 character, // nessesary to ignore as causes lots of warning #pragma warning(disable: 4786) #endif #include "CXX/Objects.hxx" #include "CXX/Extensions.hxx" #include class new_style_class: public Py::PythonClass< new_style_class > { public: new_style_class( Py::PythonClassInstance *self, Py::Tuple &args, Py::Dict &kwds ) : Py::PythonClass< new_style_class >::PythonClass( self, args, kwds ) , m_value( "default value" ) { std::cout << "new_style_class c'tor Called with " << args.length() << " normal arguments." << std::endl; Py::List names( kwds.keys() ); std::cout << "and with " << names.length() << " keyword arguments:" << std::endl; for( Py::List::size_type i=0; i< names.length(); i++ ) { Py::String name( names[i] ); std::cout << " " << name << std::endl; } } virtual ~new_style_class() { std::cout << "~new_style_class." << std::endl; } static void init_type(void) { behaviors().name( "new_style_class" ); behaviors().doc( "documentation for new_style_class class" ); behaviors().supportGetattro(); behaviors().supportSetattro(); PYCXX_ADD_NOARGS_METHOD( func_noargs, new_style_class_func_noargs, "docs for new_style_class_func_noargs" ); PYCXX_ADD_VARARGS_METHOD( func_varargs, new_style_class_func_varargs, "docs for new_style_class_func_varargs" ); PYCXX_ADD_KEYWORDS_METHOD( func_keyword, new_style_class_func_keyword, "docs for new_style_class_func_keyword" ); PYCXX_ADD_NOARGS_METHOD( func_noargs_raise_exception, new_style_class_func_noargs_raise_exception, "docs for new_style_class_func_noargs_raise_exception" ); // Call to make the type ready for use behaviors().readyType(); } Py::Object new_style_class_func_noargs( void ) { std::cout << "new_style_class_func_noargs Called." << std::endl; std::cout << "value ref count " << m_value.reference_count() << std::endl; return Py::None(); } PYCXX_NOARGS_METHOD_DECL( new_style_class, new_style_class_func_noargs ) Py::Object new_style_class_func_varargs( const Py::Tuple &args ) { std::cout << "new_style_class_func_varargs Called with " << args.length() << " normal arguments." << std::endl; return Py::None(); } PYCXX_VARARGS_METHOD_DECL( new_style_class, new_style_class_func_varargs ) Py::Object new_style_class_func_keyword( const Py::Tuple &args, const Py::Dict &kwds ) { std::cout << "new_style_class_func_keyword Called with " << args.length() << " normal arguments." << std::endl; Py::List names( kwds.keys() ); std::cout << "and with " << names.length() << " keyword arguments:" << std::endl; for( Py::List::size_type i=0; i< names.length(); i++ ) { Py::String name( names[i] ); std::cout << " " << name << std::endl; } return Py::None(); } PYCXX_KEYWORDS_METHOD_DECL( new_style_class, new_style_class_func_keyword ) Py::Object new_style_class_func_noargs_raise_exception( void ) { std::cout << "new_style_class_func_noargs_raise_exception Called." << std::endl; throw Py::RuntimeError( "its an error" ); return Py::None(); } PYCXX_NOARGS_METHOD_DECL( new_style_class, new_style_class_func_noargs_raise_exception ) Py::Object getattro( const Py::String &name_ ) { std::string name( name_.as_std_string( "utf-8" ) ); if( name == "value" ) { return m_value; } else { return genericGetAttro( name_ ); } } int setattro( const Py::String &name_, const Py::Object &value ) { std::string name( name_.as_std_string( "utf-8" ) ); if( name == "value" ) { m_value = value; return 0; } else { return genericSetAttro( name_, value ); } } Py::String m_value; }; class old_style_class: public Py::PythonExtension< old_style_class > { public: old_style_class() { } virtual ~old_style_class() { } static void init_type(void) { behaviors().name( "old_style_class" ); behaviors().doc( "documentation for old_style_class class" ); behaviors().supportGetattr(); add_noargs_method( "old_style_class_func_noargs", &old_style_class::old_style_class_func_noargs ); add_varargs_method( "old_style_class_func_varargs", &old_style_class::old_style_class_func_varargs ); add_keyword_method( "old_style_class_func_keyword", &old_style_class::old_style_class_func_keyword ); } // override functions from PythonExtension virtual Py::Object getattr( const char *name ) { return getattr_methods( name ); } Py::Object old_style_class_func_noargs( void ) { std::cout << "old_style_class_func_noargs Called." << std::endl; return Py::None(); } Py::Object old_style_class_func_varargs( const Py::Tuple &args ) { std::cout << "old_style_class_func_varargs Called with " << args.length() << " normal arguments." << std::endl; return Py::None(); } Py::Object old_style_class_func_keyword( const Py::Tuple &args, const Py::Dict &kwds ) { std::cout << "old_style_class_func_keyword Called with " << args.length() << " normal arguments." << std::endl; Py::List names( kwds.keys() ); std::cout << "and with " << names.length() << " keyword arguments:" << std::endl; for( Py::List::size_type i=0; i< names.length(); i++ ) { Py::String name( names[i] ); std::cout << " " << name << std::endl; } return Py::None(); } }; class simple_module : public Py::ExtensionModule { public: simple_module() : Py::ExtensionModule( "simple" ) // this must be name of the file on disk e.g. simple.so or simple.pyd { old_style_class::init_type(); new_style_class::init_type(); add_varargs_method("old_style_class", &simple_module::factory_old_style_class, "documentation for old_style_class()"); add_keyword_method("func", &simple_module::func, "documentation for func()"); add_keyword_method("make_instance", &simple_module::make_instance, "documentation for make_instance()"); add_keyword_method("decode_test", &simple_module::decode_test, "documentation for decode_test()"); add_keyword_method("encode_test", &simple_module::encode_test, "documentation for encode_test()"); // after initialize the moduleDictionary will exist initialize( "documentation for the simple module" ); Py::Dict d( moduleDictionary() ); d["var"] = Py::String( "var value" ); Py::Object x( new_style_class::type() ); d["new_style_class"] = x; } virtual ~simple_module() {} private: Py::Object decode_test( const Py::Tuple &args, const Py::Dict &kwds ) { Py::String s( args[0] ); return s.decode("utf-8"); } Py::Object encode_test( const Py::Tuple &args, const Py::Dict &kwds ) { Py::String s( args[0] ); return s.encode("utf-8"); } Py::Object func( const Py::Tuple &args, const Py::Dict &kwds ) { std::cout << "func Called with " << args.length() << " normal arguments." << std::endl; Py::List names( kwds.keys() ); std::cout << "and with " << names.length() << " keyword arguments:" << std::endl; for( Py::List::size_type i=0; i< names.length(); i++ ) { Py::String name( names[i] ); std::cout << " " << name << std::endl; } if( args.length() > 0 ) { Py::Object x( args[0] ); try { Py::PythonClassObject x2( x ); std::cout << "C++ pointer " << x2.getCxxObject() << std::endl; } catch( Py::TypeError &e ) { // must clear the error e.clear(); std::cout << "arg 1 is not a new_style_class" << std::endl; } } return Py::None(); } Py::Object make_instance( const Py::Tuple &args, const Py::Dict &kwds ) { std::cout << "make_instance Called with " << args.length() << " normal arguments." << std::endl; Py::List names( kwds.keys() ); std::cout << "and with " << names.length() << " keyword arguments:" << std::endl; for( Py::List::size_type i=0; i< names.length(); i++ ) { Py::String name( names[i] ); std::cout << " " << name << std::endl; } Py::Callable class_type( new_style_class::type() ); Py::PythonClassObject new_style_obj( class_type.apply( args, kwds ) ); return new_style_obj; } Py::Object factory_old_style_class( const Py::Tuple &rargs ) { Py::Object obj = Py::asObject( new old_style_class ); return obj; } }; #if defined( _WIN32 ) #define EXPORT_SYMBOL __declspec( dllexport ) #else #define EXPORT_SYMBOL #endif #if defined( PY3 ) static simple_module *simple; extern "C" EXPORT_SYMBOL PyObject *PyInit_simple() { #if defined(PY_WIN32_DELAYLOAD_PYTHON_DLL) Py::InitialisePythonIndirectPy::Interface(); #endif simple = new simple_module; return simple->module().ptr(); } // symbol required for the debug version extern "C" EXPORT_SYMBOL PyObject *PyInit_simple_d() { return PyInit_simple(); } #else static simple_module *simple; extern "C" EXPORT_SYMBOL void initsimple() { #if defined(PY_WIN32_DELAYLOAD_PYTHON_DLL) Py::InitialisePythonIndirectPy::Interface(); #endif simple = new simple_module; } // symbol required for the debug version extern "C" EXPORT_SYMBOL void initsimple_d() { initsimple(); } #endif pycxx-6.2.5/Demo/Python2/test_example.py000644 000771 000000 00000004257 11146616710 020457 0ustar00barrywheel000000 000000 #----------------------------------------------------------------------------- # # Copyright (c) 1998 - 2007, The Regents of the University of California # Produced at the Lawrence Livermore National Laboratory # All rights reserved. # # This file is part of PyCXX. For details,see http:#cxx.sourceforge.net/. The # full copyright notice is contained in the file COPYRIGHT located at the root # of the PyCXX distribution. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # - Redistributions of source code must retain the above copyright notice, # this list of conditions and the disclaimer below. # - Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the disclaimer (as noted below) in the # documentation and/or materials provided with the distribution. # - Neither the name of the UC/LLNL nor the names of its contributors may be # used to endorse or promote products derived from this software without # specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF # CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH # DAMAGE. # #----------------------------------------------------------------------------- import sys sys.path.insert( 0, 'pyds%d%d' % (sys.version_info[0], sys.version_info[1]) ) import example example.test() pycxx-6.2.5/Demo/Python2/test_pycxx_iter.py000644 000771 000000 00000000445 11146616710 021215 0ustar00barrywheel000000 000000 import sys sys.path.insert( 0, 'pyds%d%d' % (sys.version_info[0], sys.version_info[1]) ) import pycxx_iter IT=pycxx_iter.IterT(5,7) for i in IT: print i, IT print "refcount of IT:",sys.getrefcount(IT) for i in IT.reversed(): print i print "refcount of IT:",sys.getrefcount(IT) pycxx-6.2.5/Demo/Python2/test_simple.py000644 000771 000000 00000003371 11347772667 020332 0ustar00barrywheel000000 000000 import sys import simple print( '--- module func ---' ) simple.func() simple.func( 4, 5 ) simple.func( 4, 5, name=6, value=7 ) print( '--- old_style_class func ---' ) old_style_class = simple.old_style_class() old_style_class.old_style_class_func_noargs() old_style_class.old_style_class_func_varargs() old_style_class.old_style_class_func_varargs( 4 ) old_style_class.old_style_class_func_keyword() old_style_class.old_style_class_func_keyword( name=6, value=7 ) old_style_class.old_style_class_func_keyword( 4, 5 ) old_style_class.old_style_class_func_keyword( 4, 5, name=6, value=7 ) print( '--- Derived func ---' ) class Derived(simple.new_style_class): def __init__( self ): simple.new_style_class.__init__( self ) def derived_func( self ): print( 'derived_func' ) super( Derived, self ).func_noargs() def func_noargs( self ): print( 'derived func_noargs' ) d = Derived() print( dir( d ) ) d.derived_func() d.func_noargs() d.func_varargs() d.func_varargs( 4 ) d.func_keyword() d.func_keyword( name=6, value=7 ) d.func_keyword( 4, 5 ) d.func_keyword( 4, 5, name=6, value=7 ) print( d.value ) d.value = "a string" print( d.value ) d.new_var = 99 print( '--- new_style_class func ---' ) new_style_class = simple.new_style_class() print( dir( new_style_class ) ) new_style_class.func_noargs() new_style_class.func_varargs() new_style_class.func_varargs( 4 ) new_style_class.func_keyword() new_style_class.func_keyword( name=6, value=7 ) new_style_class.func_keyword( 4, 5 ) new_style_class.func_keyword( 4, 5, name=6, value=7 ) try: new_style_class.func_noargs_raise_exception() print 'Error: did not raised RuntimeError' sys.exit( 1 ) except RuntimeError, e: print 'Raised %r' % (str(e),) new_style_class = None pycxx-6.2.5/CXX/Config.hxx000644 000771 000000 00000004344 11146066410 015555 0ustar00barrywheel000000 000000 //----------------------------------------------------------------------------- // // Copyright (c) 1998 - 2007, The Regents of the University of California // Produced at the Lawrence Livermore National Laboratory // All rights reserved. // // This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The // full copyright notice is contained in the file COPYRIGHT located at the root // of the PyCXX distribution. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // - Redistributions of source code must retain the above copyright notice, // this list of conditions and the disclaimer below. // - Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the disclaimer (as noted below) in the // documentation and/or materials provided with the distribution. // - Neither the name of the UC/LLNL nor the names of its contributors may be // used to endorse or promote products derived from this software without // specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF // CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH // DAMAGE. // //----------------------------------------------------------------------------- #include "CXX/WrapPython.h" #if PY_MAJOR_VERSION == 2 #include "CXX/Python2/Config.hxx" #else #include "CXX/Python3/Config.hxx" #endif pycxx-6.2.5/CXX/Exception.hxx000644 000771 000000 00000004352 11146066410 016305 0ustar00barrywheel000000 000000 //----------------------------------------------------------------------------- // // Copyright (c) 1998 - 2007, The Regents of the University of California // Produced at the Lawrence Livermore National Laboratory // All rights reserved. // // This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The // full copyright notice is contained in the file COPYRIGHT located at the root // of the PyCXX distribution. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // - Redistributions of source code must retain the above copyright notice, // this list of conditions and the disclaimer below. // - Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the disclaimer (as noted below) in the // documentation and/or materials provided with the distribution. // - Neither the name of the UC/LLNL nor the names of its contributors may be // used to endorse or promote products derived from this software without // specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF // CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH // DAMAGE. // //----------------------------------------------------------------------------- #include "CXX/WrapPython.h" #if PY_MAJOR_VERSION == 2 #include "CXX/Python2/Exception.hxx" #else #include "CXX/Python3/Exception.hxx" #endif pycxx-6.2.5/CXX/Extensions.hxx000644 000771 000000 00000004354 11146066410 016510 0ustar00barrywheel000000 000000 //----------------------------------------------------------------------------- // // Copyright (c) 1998 - 2007, The Regents of the University of California // Produced at the Lawrence Livermore National Laboratory // All rights reserved. // // This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The // full copyright notice is contained in the file COPYRIGHT located at the root // of the PyCXX distribution. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // - Redistributions of source code must retain the above copyright notice, // this list of conditions and the disclaimer below. // - Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the disclaimer (as noted below) in the // documentation and/or materials provided with the distribution. // - Neither the name of the UC/LLNL nor the names of its contributors may be // used to endorse or promote products derived from this software without // specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF // CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH // DAMAGE. // //----------------------------------------------------------------------------- #include "CXX/WrapPython.h" #if PY_MAJOR_VERSION == 2 #include "CXX/Python2/Extensions.hxx" #else #include "CXX/Python3/Extensions.hxx" #endif pycxx-6.2.5/CXX/IndirectPythonInterface.hxx000644 000771 000000 00000000252 11146072165 021132 0ustar00barrywheel000000 000000 #include "CXX/WrapPython.h" #if PY_MAJOR_VERSION == 2 #include "CXX/Python2/IndirectPythonInterface.hxx" #else #include "CXX/Python3/IndirectPythonInterface.hxx" #endif pycxx-6.2.5/CXX/Objects.hxx000644 000771 000000 00000004346 11146066410 015743 0ustar00barrywheel000000 000000 //----------------------------------------------------------------------------- // // Copyright (c) 1998 - 2007, The Regents of the University of California // Produced at the Lawrence Livermore National Laboratory // All rights reserved. // // This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The // full copyright notice is contained in the file COPYRIGHT located at the root // of the PyCXX distribution. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // - Redistributions of source code must retain the above copyright notice, // this list of conditions and the disclaimer below. // - Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the disclaimer (as noted below) in the // documentation and/or materials provided with the distribution. // - Neither the name of the UC/LLNL nor the names of its contributors may be // used to endorse or promote products derived from this software without // specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF // CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH // DAMAGE. // //----------------------------------------------------------------------------- #include "CXX/WrapPython.h" #if PY_MAJOR_VERSION == 2 #include "CXX/Python2/Objects.hxx" #else #include "CXX/Python3/Objects.hxx" #endif pycxx-6.2.5/CXX/Python2/000755 000771 000000 00000000000 12204160454 015154 5ustar00barrywheel000000 000000 pycxx-6.2.5/CXX/Python3/000755 000771 000000 00000000000 12204160454 015155 5ustar00barrywheel000000 000000 pycxx-6.2.5/CXX/Version.hxx000644 000771 000000 00000004666 12204157547 016014 0ustar00barrywheel000000 000000 //----------------------------------------------------------------------------- // // Copyright (c) 1998 - 2007, The Regents of the University of California // Produced at the Lawrence Livermore National Laboratory // All rights reserved. // // This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The // full copyright notice is contained in the file COPYRIGHT located at the root // of the PyCXX distribution. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // - Redistributions of source code must retain the above copyright notice, // this list of conditions and the disclaimer below. // - Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the disclaimer (as noted below) in the // documentation and/or materials provided with the distribution. // - Neither the name of the UC/LLNL nor the names of its contributors may be // used to endorse or promote products derived from this software without // specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF // CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH // DAMAGE. // //----------------------------------------------------------------------------- #ifndef __PyCXX_version_hxx__ #define __PyCXX_version_hxx__ #define PYCXX_VERSION_MAJOR 6 #define PYCXX_VERSION_MINOR 2 #define PYCXX_VERSION_PATCH 5 #define PYCXX_MAKEVERSION( major, minor, patch ) ((major<<16)|(minor<<8)|(patch)) #define PYCXX_VERSION PYCXX_MAKEVERSION( PYCXX_VERSION_MAJOR, PYCXX_VERSION_MINOR, PYCXX_VERSION_PATCH ) #endif pycxx-6.2.5/CXX/WrapPython.h000644 000771 000000 00000005561 11771611632 016113 0ustar00barrywheel000000 000000 //----------------------------------------------------------------------------- // // Copyright (c) 1998 - 2007, The Regents of the University of California // Produced at the Lawrence Livermore National Laboratory // All rights reserved. // // This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The // full copyright notice is contained in the file COPYRIGHT located at the root // of the PyCXX distribution. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // - Redistributions of source code must retain the above copyright notice, // this list of conditions and the disclaimer below. // - Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the disclaimer (as noted below) in the // documentation and/or materials provided with the distribution. // - Neither the name of the UC/LLNL nor the names of its contributors may be // used to endorse or promote products derived from this software without // specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF // CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH // DAMAGE. // //----------------------------------------------------------------------------- #ifndef __PyCXX_wrap_python_hxx__ #define __PyCXX_wrap_python_hxx__ // On some platforms we have to include time.h to get select defined #if !defined(__WIN32__) && !defined(WIN32) && !defined(_WIN32) && !defined(_WIN64) #include #endif // Prevent multiple conflicting definitions of swab from stdlib.h and unistd.h #if defined(__sun) || defined(sun) #if defined(_XPG4) #undef _XPG4 #endif #endif // Python.h will redefine these and generate warning in the process #undef _XOPEN_SOURCE #undef _POSIX_C_SOURCE // pull in python definitions #include // fix issue with Python assuming that isspace, toupper etc are macros #if defined(isspace) #undef isspace #undef isupper #undef islower #undef isalnum #undef isalpha #undef toupper #undef tolower #endif #endif pycxx-6.2.5/CXX/Python3/Config.hxx000644 000771 000000 00000007741 11704271056 017131 0ustar00barrywheel000000 000000 //----------------------------------------------------------------------------- // // Copyright (c) 1998 - 2007, The Regents of the University of California // Produced at the Lawrence Livermore National Laboratory // All rights reserved. // // This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The // full copyright notice is contained in the file COPYRIGHT located at the root // of the PyCXX distribution. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // - Redistributions of source code must retain the above copyright notice, // this list of conditions and the disclaimer below. // - Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the disclaimer (as noted below) in the // documentation and/or materials provided with the distribution. // - Neither the name of the UC/LLNL nor the names of its contributors may be // used to endorse or promote products derived from this software without // specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF // CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH // DAMAGE. // //----------------------------------------------------------------------------- #ifndef __PyCXX_config_hh__ #define __PyCXX_config_hh__ // // Microsoft VC++ 6.0 has no traits // #if defined( _MSC_VER ) # define STANDARD_LIBRARY_HAS_ITERATOR_TRAITS 1 #elif defined( __GNUC__ ) # if __GNUC__ >= 3 # define STANDARD_LIBRARY_HAS_ITERATOR_TRAITS 1 # else # define STANDARD_LIBRARY_HAS_ITERATOR_TRAITS 0 #endif // // Assume all other compilers do // #else // Macros to deal with deficiencies in compilers # define STANDARD_LIBRARY_HAS_ITERATOR_TRAITS 1 #endif #if STANDARD_LIBRARY_HAS_ITERATOR_TRAITS # define random_access_iterator_parent(itemtype) std::iterator #else # define random_access_iterator_parent(itemtype) std::random_access_iterator #endif // // Which C++ standard is in use? // #if defined( _MSC_VER ) # if _MSC_VER <= 1200 // MSVC++ 6.0 # define PYCXX_ISO_CPP_LIB 0 # define STR_STREAM # define TEMPLATE_TYPENAME class # else # define PYCXX_ISO_CPP_LIB 1 # define STR_STREAM # define TEMPLATE_TYPENAME typename # endif #elif defined( __GNUC__ ) # if __GNUC__ >= 3 # define PYCXX_ISO_CPP_LIB 1 # define STR_STREAM # define TEMPLATE_TYPENAME typename # else # define PYCXX_ISO_CPP_LIB 0 # define STR_STREAM # define TEMPLATE_TYPENAME class # endif #endif #if PYCXX_ISO_CPP_LIB # define STR_STREAM # define OSTRSTREAM ostringstream # define EXPLICIT_TYPENAME typename # define EXPLICIT_CLASS class # define TEMPLATE_TYPENAME typename #else # define STR_STREAM # define OSTRSTREAM ostrstream # define EXPLICIT_TYPENAME # define EXPLICIT_CLASS # define TEMPLATE_TYPENAME class #endif // before 3.2 Py_hash_t was missing #ifndef PY_MAJOR_VERSION #error not defined PY_MAJOR_VERSION #endif #if PY_MINOR_VERSION < 2 typedef long int Py_hash_t; #endif #endif // __PyCXX_config_hh__ pycxx-6.2.5/CXX/Python3/CxxDebug.hxx000644 000771 000000 00000000402 11146615306 017420 0ustar00barrywheel000000 000000 // // CxxDebug.hxx // // Copyright (c) 2008 Barry A. Scott // #ifndef __CXX_Debug_hxx #define __CXX_Debug_hxx // // Functions useful when debugging PyCXX // #ifdef PYCXX_DEBUG extern void bpt(); extern void printRefCount( PyObject *obj ); #endif #endif pycxx-6.2.5/CXX/Python3/Exception.hxx000644 000771 000000 00000016173 11400430272 017647 0ustar00barrywheel000000 000000 //----------------------------------------------------------------------------- // // Copyright (c) 1998 - 2007, The Regents of the University of California // Produced at the Lawrence Livermore National Laboratory // All rights reserved. // // This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The // full copyright notice is contained in the file COPYRIGHT located at the root // of the PyCXX distribution. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // - Redistributions of source code must retain the above copyright notice, // this list of conditions and the disclaimer below. // - Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the disclaimer (as noted below) in the // documentation and/or materials provided with the distribution. // - Neither the name of the UC/LLNL nor the names of its contributors may be // used to endorse or promote products derived from this software without // specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF // CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH // DAMAGE. // //----------------------------------------------------------------------------- #ifndef __CXX_Exception_h #define __CXX_Exception_h #include "CXX/WrapPython.h" #include "CXX/Version.hxx" #include "CXX/Python3/Config.hxx" #include "CXX/Python3/CxxDebug.hxx" #include "CXX/Python3/IndirectPythonInterface.hxx" #include #include // This mimics the Python structure, in order to minimize confusion namespace Py { class ExtensionExceptionType; class Object; class Exception { public: Exception( ExtensionExceptionType &exception, const std::string &reason ); Exception( ExtensionExceptionType &exception, Object &reason ); explicit Exception () {} Exception (const std::string &reason) { PyErr_SetString( Py::_Exc_RuntimeError(), reason.c_str() ); } Exception( PyObject *exception, const std::string &reason ) { PyErr_SetString( exception, reason.c_str() ); } Exception( PyObject *exception, Object &reason ); void clear() // clear the error // technically but not philosophically const { PyErr_Clear(); } }; // Abstract class StandardError: public Exception { protected: explicit StandardError() {} }; class LookupError: public StandardError { protected: explicit LookupError() {} }; class ArithmeticError: public StandardError { protected: explicit ArithmeticError() {} }; class EnvironmentError: public StandardError { protected: explicit EnvironmentError() {} }; // Concrete class TypeError: public StandardError { public: TypeError (const std::string& reason) : StandardError() { PyErr_SetString( Py::_Exc_TypeError(),reason.c_str() ); } }; class IndexError: public LookupError { public: IndexError (const std::string& reason) : LookupError() { PyErr_SetString( Py::_Exc_IndexError(), reason.c_str() ); } }; class AttributeError: public StandardError { public: AttributeError (const std::string& reason) : StandardError() { PyErr_SetString( Py::_Exc_AttributeError(), reason.c_str() ); } }; class NameError: public StandardError { public: NameError (const std::string& reason) : StandardError() { PyErr_SetString( Py::_Exc_NameError(), reason.c_str() ); } }; class RuntimeError: public StandardError { public: RuntimeError (const std::string& reason) : StandardError() { PyErr_SetString( Py::_Exc_RuntimeError(), reason.c_str() ); } }; class NotImplementedError: public StandardError { public: NotImplementedError (const std::string& reason) : StandardError() { PyErr_SetString (Py::_Exc_NotImplementedError(), reason.c_str()); } }; class SystemError: public StandardError { public: SystemError (const std::string& reason) : StandardError() { PyErr_SetString( Py::_Exc_SystemError(),reason.c_str() ); } }; class KeyError: public LookupError { public: KeyError (const std::string& reason) : LookupError() { PyErr_SetString( Py::_Exc_KeyError(),reason.c_str() ); } }; class ValueError: public StandardError { public: ValueError (const std::string& reason) : StandardError() { PyErr_SetString( Py::_Exc_ValueError(), reason.c_str() ); } }; class OverflowError: public ArithmeticError { public: OverflowError (const std::string& reason) : ArithmeticError() { PyErr_SetString( Py::_Exc_OverflowError(), reason.c_str() ); } }; class ZeroDivisionError: public ArithmeticError { public: ZeroDivisionError (const std::string& reason) : ArithmeticError() { PyErr_SetString( Py::_Exc_ZeroDivisionError(), reason.c_str() ); } }; class FloatingPointError: public ArithmeticError { public: FloatingPointError (const std::string& reason) : ArithmeticError() { PyErr_SetString( Py::_Exc_FloatingPointError(), reason.c_str() ); } }; class MemoryError: public StandardError { public: MemoryError (const std::string& reason) : StandardError() { PyErr_SetString( Py::_Exc_MemoryError(), reason.c_str() ); } }; class SystemExit: public StandardError { public: SystemExit (const std::string& reason) : StandardError() { PyErr_SetString( Py::_Exc_SystemExit(),reason.c_str() ); } }; }// Py #endif pycxx-6.2.5/CXX/Python3/ExtensionModule.hxx000644 000771 000000 00000020773 11615064135 021045 0ustar00barrywheel000000 000000 //----------------------------------------------------------------------------- // // Copyright (c) 1998 - 2007, The Regents of the University of California // Produced at the Lawrence Livermore National Laboratory // All rights reserved. // // This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The // full copyright notice is contained in the file COPYRIGHT located at the root // of the PyCXX distribution. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // - Redistributions of source code must retain the above copyright notice, // this list of conditions and the disclaimer below. // - Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the disclaimer (as noted below) in the // documentation and/or materials provided with the distribution. // - Neither the name of the UC/LLNL nor the names of its contributors may be // used to endorse or promote products derived from this software without // specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF // CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH // DAMAGE. // //----------------------------------------------------------------------------- #ifndef __CXX_ExtensionModule__h #define __CXX_ExtensionModule__h namespace Py { class ExtensionModuleBase { public: ExtensionModuleBase( const char *name ); virtual ~ExtensionModuleBase(); Module module( void ) const; // only valid after initialize() has been called Dict moduleDictionary( void ) const; // only valid after initialize() has been called virtual Object invoke_method_noargs( void *method_def ) = 0; virtual Object invoke_method_keyword( void *method_def, const Tuple &_args, const Dict &_keywords ) = 0; virtual Object invoke_method_varargs( void *method_def, const Tuple &_args ) = 0; const std::string &name() const; const std::string &fullName() const; // what is returned from PyInit_ function Object moduleObject( void ) const; protected: // Initialize the module void initialize( const char *module_doc ); const std::string m_module_name; const std::string m_full_module_name; MethodTable m_method_table; PyModuleDef m_module_def; PyObject *m_module; private: // // prevent the compiler generating these unwanted functions // ExtensionModuleBase( const ExtensionModuleBase & ); //unimplemented void operator=( const ExtensionModuleBase & ); //unimplemented }; // Note: Python calls noargs as varargs buts args==NULL extern "C" PyObject *method_noargs_call_handler( PyObject *_self_and_name_tuple, PyObject * ); extern "C" PyObject *method_varargs_call_handler( PyObject *_self_and_name_tuple, PyObject *_args ); extern "C" PyObject *method_keyword_call_handler( PyObject *_self_and_name_tuple, PyObject *_args, PyObject *_keywords ); template class ExtensionModule : public ExtensionModuleBase { public: ExtensionModule( const char *name ) : ExtensionModuleBase( name ) {} virtual ~ExtensionModule() {} protected: typedef Object (T::*method_noargs_function_t)(); typedef Object (T::*method_varargs_function_t)( const Tuple &args ); typedef Object (T::*method_keyword_function_t)( const Tuple &args, const Dict &kws ); typedef std::map *> method_map_t; static void add_noargs_method( const char *name, method_noargs_function_t function, const char *doc="" ) { method_map_t &mm = methods(); mm[ std::string( name ) ] = new MethodDefExt( name, function, method_noargs_call_handler, doc ); } static void add_varargs_method( const char *name, method_varargs_function_t function, const char *doc="" ) { method_map_t &mm = methods(); mm[ std::string( name ) ] = new MethodDefExt( name, function, method_varargs_call_handler, doc ); } static void add_keyword_method( const char *name, method_keyword_function_t function, const char *doc="" ) { method_map_t &mm = methods(); mm[ std::string( name ) ] = new MethodDefExt( name, function, method_keyword_call_handler, doc ); } void initialize( const char *module_doc="" ) { ExtensionModuleBase::initialize( module_doc ); Dict dict( moduleDictionary() ); // // put each of the methods into the modules dictionary // so that we get called back at the function in T. // method_map_t &mm = methods(); EXPLICIT_TYPENAME method_map_t::const_iterator i = mm.begin(); EXPLICIT_TYPENAME method_map_t::const_iterator i_end = mm.end(); for ( ; i != i_end; ++i ) { MethodDefExt *method_def = (*i).second; static PyObject *self = PyCapsule_New( this, NULL, NULL ); Tuple args( 2 ); args[0] = Object( self, true ); args[1] = Object( PyCapsule_New( method_def, NULL, NULL ), true ); PyObject *func = PyCFunction_New ( &method_def->ext_meth_def, new_reference_to( args ) ); method_def->py_method = Object( func, true ); dict[ (*i).first ] = method_def->py_method; } } protected: // Tom Malcolmson reports that derived classes need access to these static method_map_t &methods( void ) { static method_map_t *map_of_methods = NULL; if( map_of_methods == NULL ) map_of_methods = new method_map_t; return *map_of_methods; } // this invoke function must be called from within a try catch block virtual Object invoke_method_noargs( void *method_def ) { // cast up to the derived class, method_def and call T *self = static_cast( this ); MethodDefExt *meth_def = reinterpret_cast *>( method_def ); return (self->*meth_def->ext_noargs_function)(); } // this invoke function must be called from within a try catch block virtual Object invoke_method_varargs( void *method_def, const Tuple &args ) { // cast up to the derived class, method_def and call T *self = static_cast( this ); MethodDefExt *meth_def = reinterpret_cast *>( method_def ); return (self->*meth_def->ext_varargs_function)( args ); } // this invoke function must be called from within a try catch block virtual Object invoke_method_keyword( void *method_def, const Tuple &args, const Dict &keywords ) { // cast up to the derived class, method_def and call T *self = static_cast( this ); MethodDefExt *meth_def = reinterpret_cast *>( method_def ); return (self->*meth_def->ext_keyword_function)( args, keywords ); } private: // // prevent the compiler generating these unwanted functions // ExtensionModule( const ExtensionModule & ); //unimplemented void operator=( const ExtensionModule & ); //unimplemented }; } // Namespace Py // End of __CXX_ExtensionModule__h #endif pycxx-6.2.5/CXX/Python3/ExtensionOldType.hxx000644 000771 000000 00000031624 11615064135 021175 0ustar00barrywheel000000 000000 //----------------------------------------------------------------------------- // // Copyright (c) 1998 - 2007, The Regents of the University of California // Produced at the Lawrence Livermore National Laboratory // All rights reserved. // // This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The // full copyright notice is contained in the file COPYRIGHT located at the root // of the PyCXX distribution. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // - Redistributions of source code must retain the above copyright notice, // this list of conditions and the disclaimer below. // - Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the disclaimer (as noted below) in the // documentation and/or materials provided with the distribution. // - Neither the name of the UC/LLNL nor the names of its contributors may be // used to endorse or promote products derived from this software without // specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF // CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH // DAMAGE. // //----------------------------------------------------------------------------- #ifndef __CXX_ExtensionOldType__h #define __CXX_ExtensionOldType__h namespace Py { template class PythonExtension : public PythonExtensionBase { public: static PyTypeObject *type_object() { return behaviors().type_object(); } static bool check( PyObject *p ) { // is p like me? return p->ob_type == type_object(); } static bool check( const Object &ob ) { return check( ob.ptr() ); } // // every object needs getattr implemented // to support methods // virtual Object getattr( const char *name ) { return getattr_methods( name ); } PyObject *selfPtr() { return this; } Object self() { return asObject( this ); } protected: explicit PythonExtension() : PythonExtensionBase() { PyObject_Init( this, type_object() ); // every object must support getattr behaviors().supportGetattr(); } virtual ~PythonExtension() {} static PythonType &behaviors() { static PythonType* p; if( p == NULL ) { #if defined( _CPPRTTI ) || defined( __GNUG__ ) const char *default_name =( typeid( T ) ).name(); #else const char *default_name = "unknown"; #endif p = new PythonType( sizeof( T ), 0, default_name ); p->set_tp_dealloc( extension_object_deallocator ); } return *p; } typedef Object (T::*method_noargs_function_t)(); typedef Object (T::*method_varargs_function_t)( const Tuple &args ); typedef Object (T::*method_keyword_function_t)( const Tuple &args, const Dict &kws ); typedef std::map *> method_map_t; // support the default attributes, __name__, __doc__ and methods virtual Object getattr_default( const char *_name ) { std::string name( _name ); if( name == "__name__" && type_object()->tp_name != NULL ) { return Py::String( type_object()->tp_name ); } if( name == "__doc__" && type_object()->tp_doc != NULL ) { return Py::String( type_object()->tp_doc ); } // trying to fake out being a class for help() // else if( name == "__bases__" ) // { // return Py::Tuple( 0 ); // } // else if( name == "__module__" ) // { // return Py::Nothing(); // } // else if( name == "__dict__" ) // { // return Py::Dict(); // } return getattr_methods( _name ); } // turn a name into function object virtual Object getattr_methods( const char *_name ) { std::string name( _name ); method_map_t &mm = methods(); // see if name exists and get entry with method EXPLICIT_TYPENAME method_map_t::const_iterator i = mm.find( name ); if( i == mm.end() ) { if( name == "__methods__" ) { List methods; i = mm.begin(); EXPLICIT_TYPENAME method_map_t::const_iterator i_end = mm.end(); for( ; i != i_end; ++i ) methods.append( String( (*i).first ) ); return methods; } throw AttributeError( name ); } MethodDefExt *method_def = i->second; Tuple self( 2 ); self[0] = Object( this ); self[1] = Object( PyCapsule_New( method_def, NULL, NULL ), true ); PyObject *func = PyCFunction_New( &method_def->ext_meth_def, self.ptr() ); return Object(func, true); } // check that all methods added are unique static void check_unique_method_name( const char *name ) { method_map_t &mm = methods(); EXPLICIT_TYPENAME method_map_t::const_iterator i; i = mm.find( name ); if( i != mm.end() ) throw AttributeError( name ); } static void add_noargs_method( const char *name, method_noargs_function_t function, const char *doc="" ) { check_unique_method_name( name ); method_map_t &mm = methods(); mm[ std::string( name ) ] = new MethodDefExt( name, function, method_noargs_call_handler, doc ); } static void add_varargs_method( const char *name, method_varargs_function_t function, const char *doc="" ) { check_unique_method_name( name ); method_map_t &mm = methods(); mm[ std::string( name ) ] = new MethodDefExt( name, function, method_varargs_call_handler, doc ); } static void add_keyword_method( const char *name, method_keyword_function_t function, const char *doc="" ) { check_unique_method_name( name ); method_map_t &mm = methods(); mm[ std::string( name ) ] = new MethodDefExt( name, function, method_keyword_call_handler, doc ); } private: static method_map_t &methods( void ) { static method_map_t *map_of_methods = NULL; if( map_of_methods == NULL ) map_of_methods = new method_map_t; return *map_of_methods; } // Note: Python calls noargs as varargs buts args==NULL static PyObject *method_noargs_call_handler( PyObject *_self_and_name_tuple, PyObject * ) { try { Tuple self_and_name_tuple( _self_and_name_tuple ); PyObject *self_in_cobject = self_and_name_tuple[0].ptr(); T *self = static_cast( self_in_cobject ); MethodDefExt *meth_def = reinterpret_cast *>( PyCapsule_GetPointer( self_and_name_tuple[1].ptr(), NULL ) ); Object result; // Adding try & catch in case of STL debug-mode exceptions. #ifdef _STLP_DEBUG try { result = (self->*meth_def->ext_noargs_function)(); } catch( std::__stl_debug_exception ) { // throw cxx::RuntimeError( sErrMsg ); throw RuntimeError( "Error message not set yet." ); } #else result = (self->*meth_def->ext_noargs_function)(); #endif // _STLP_DEBUG return new_reference_to( result.ptr() ); } catch( Exception & ) { return 0; } } static PyObject *method_varargs_call_handler( PyObject *_self_and_name_tuple, PyObject *_args ) { try { Tuple self_and_name_tuple( _self_and_name_tuple ); PyObject *self_in_cobject = self_and_name_tuple[0].ptr(); T *self = static_cast( self_in_cobject ); MethodDefExt *meth_def = reinterpret_cast *>( PyCapsule_GetPointer( self_and_name_tuple[1].ptr(), NULL ) ); Tuple args( _args ); Object result; // Adding try & catch in case of STL debug-mode exceptions. #ifdef _STLP_DEBUG try { result = (self->*meth_def->ext_varargs_function)( args ); } catch( std::__stl_debug_exception ) { throw RuntimeError( "Error message not set yet." ); } #else result = (self->*meth_def->ext_varargs_function)( args ); #endif // _STLP_DEBUG return new_reference_to( result.ptr() ); } catch( Exception & ) { return 0; } } static PyObject *method_keyword_call_handler( PyObject *_self_and_name_tuple, PyObject *_args, PyObject *_keywords ) { try { Tuple self_and_name_tuple( _self_and_name_tuple ); PyObject *self_in_cobject = self_and_name_tuple[0].ptr(); T *self = static_cast( self_in_cobject ); MethodDefExt *meth_def = reinterpret_cast *>( PyCapsule_GetPointer( self_and_name_tuple[1].ptr(), NULL ) ); Tuple args( _args ); // _keywords may be NULL so be careful about the way the dict is created Dict keywords; if( _keywords != NULL ) keywords = Dict( _keywords ); Object result( ( self->*meth_def->ext_keyword_function )( args, keywords ) ); return new_reference_to( result.ptr() ); } catch( Exception & ) { return 0; } } static void extension_object_deallocator( PyObject* t ) { delete (T *)( t ); } // // prevent the compiler generating these unwanted functions // explicit PythonExtension( const PythonExtension &other ); void operator=( const PythonExtension &rhs ); }; // // ExtensionObject is an Object that will accept only T's. // template class ExtensionObject: public Object { public: explicit ExtensionObject( PyObject *pyob ) : Object( pyob ) { validate(); } ExtensionObject( const ExtensionObject &other ) : Object( *other ) { validate(); } ExtensionObject( const Object &other ) : Object( *other ) { validate(); } ExtensionObject &operator=( const Object &rhs ) { return( *this = *rhs ); } ExtensionObject &operator=( PyObject *rhsp ) { if( ptr() != rhsp ) set( rhsp ); return *this; } virtual bool accepts( PyObject *pyob ) const { return( pyob && T::check( pyob ) ); } // // Obtain a pointer to the PythonExtension object // T *extensionObject( void ) { return static_cast( ptr() ); } }; } // Namespace Py // End of __CXX_ExtensionOldType__h #endif pycxx-6.2.5/CXX/Python3/Extensions.hxx000644 000771 000000 00000015652 11230627123 020055 0ustar00barrywheel000000 000000 //----------------------------------------------------------------------------- // // Copyright (c) 1998 - 2007, The Regents of the University of California // Produced at the Lawrence Livermore National Laboratory // All rights reserved. // // This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The // full copyright notice is contained in the file COPYRIGHT located at the root // of the PyCXX distribution. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // - Redistributions of source code must retain the above copyright notice, // this list of conditions and the disclaimer below. // - Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the disclaimer (as noted below) in the // documentation and/or materials provided with the distribution. // - Neither the name of the UC/LLNL nor the names of its contributors may be // used to endorse or promote products derived from this software without // specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF // CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH // DAMAGE. // //----------------------------------------------------------------------------- #ifndef __CXX_Extensions__h #define __CXX_Extensions__h #ifdef _MSC_VER // disable warning C4786: symbol greater than 255 character, // okay to ignore #pragma warning( disable: 4786 ) #endif #include "CXX/WrapPython.h" #include "CXX/Version.hxx" #include "CXX/Python3/Config.hxx" #include "CXX/Python3/CxxDebug.hxx" #include "CXX/Python3/Objects.hxx" extern "C" { extern PyObject py_object_initializer; } #include #include // ---------------------------------------------------------------------- namespace Py { class ExtensionModuleBase; // Make an Exception Type for use in raising custom exceptions class ExtensionExceptionType : public Object { public: ExtensionExceptionType(); virtual ~ExtensionExceptionType(); // call init to create the type void init( ExtensionModuleBase &module, const std::string &name, ExtensionExceptionType &parent ); void init( ExtensionModuleBase &module, const std::string &name ); }; class MethodTable { public: MethodTable(); virtual ~MethodTable(); void add( const char *method_name, PyCFunction f, const char *doc="", int flag=1 ); PyMethodDef *table(); protected: std::vector t; // accumulator of PyMethodDef's PyMethodDef *mt; // Actual method table produced when full static PyMethodDef method( const char* method_name, PyCFunction f, int flags=1, const char* doc="" ); private: // // prevent the compiler generating these unwanted functions // MethodTable( const MethodTable &m ); //unimplemented void operator=( const MethodTable &m ); //unimplemented }; // end class MethodTable // Note: Python calls noargs as varargs buts args==NULL extern "C" typedef PyObject *(*method_noargs_call_handler_t)( PyObject *_self, PyObject * ); extern "C" typedef PyObject *(*method_varargs_call_handler_t)( PyObject *_self, PyObject *_args ); extern "C" typedef PyObject *(*method_keyword_call_handler_t)( PyObject *_self, PyObject *_args, PyObject *_dict ); template class MethodDefExt : public PyMethodDef { public: typedef Object (T::*method_noargs_function_t)(); typedef Object (T::*method_varargs_function_t)( const Tuple &args ); typedef Object (T::*method_keyword_function_t)( const Tuple &args, const Dict &kws ); // NOARGS MethodDefExt ( const char *_name, method_noargs_function_t _function, method_noargs_call_handler_t _handler, const char *_doc ) { ext_meth_def.ml_name = const_cast( _name ); ext_meth_def.ml_meth = reinterpret_cast( _handler ); ext_meth_def.ml_flags = METH_NOARGS; ext_meth_def.ml_doc = const_cast( _doc ); ext_noargs_function = _function; ext_varargs_function = NULL; ext_keyword_function = NULL; } // VARARGS MethodDefExt ( const char *_name, method_varargs_function_t _function, method_varargs_call_handler_t _handler, const char *_doc ) { ext_meth_def.ml_name = const_cast( _name ); ext_meth_def.ml_meth = reinterpret_cast( _handler ); ext_meth_def.ml_flags = METH_VARARGS; ext_meth_def.ml_doc = const_cast( _doc ); ext_noargs_function = NULL; ext_varargs_function = _function; ext_keyword_function = NULL; } // VARARGS + KEYWORD MethodDefExt ( const char *_name, method_keyword_function_t _function, method_keyword_call_handler_t _handler, const char *_doc ) { ext_meth_def.ml_name = const_cast( _name ); ext_meth_def.ml_meth = reinterpret_cast( _handler ); ext_meth_def.ml_flags = METH_VARARGS|METH_KEYWORDS; ext_meth_def.ml_doc = const_cast( _doc ); ext_noargs_function = NULL; ext_varargs_function = NULL; ext_keyword_function = _function; } ~MethodDefExt() {} PyMethodDef ext_meth_def; method_noargs_function_t ext_noargs_function; method_varargs_function_t ext_varargs_function; method_keyword_function_t ext_keyword_function; Object py_method; }; } // Namespace Py #include "CXX/Python3/ExtensionModule.hxx" #include "CXX/Python3/PythonType.hxx" #include "CXX/Python3/ExtensionTypeBase.hxx" #include "CXX/Python3/ExtensionOldType.hxx" #include "CXX/Python3/ExtensionType.hxx" // End of CXX_Extensions.h #endif pycxx-6.2.5/CXX/Python3/ExtensionType.hxx000644 000771 000000 00000033070 11367330334 020534 0ustar00barrywheel000000 000000 //----------------------------------------------------------------------------- // // Copyright (c) 1998 - 2007, The Regents of the University of California // Produced at the Lawrence Livermore National Laboratory // All rights reserved. // // This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The // full copyright notice is contained in the file COPYRIGHT located at the root // of the PyCXX distribution. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // - Redistributions of source code must retain the above copyright notice, // this list of conditions and the disclaimer below. // - Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the disclaimer (as noted below) in the // documentation and/or materials provided with the distribution. // - Neither the name of the UC/LLNL nor the names of its contributors may be // used to endorse or promote products derived from this software without // specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF // CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH // DAMAGE. // //----------------------------------------------------------------------------- #ifndef __CXX_ExtensionClass__h #define __CXX_ExtensionClass__h #define PYCXX_NOARGS_METHOD_NAME( NAME ) _callNoArgsMethod__##NAME #define PYCXX_VARARGS_METHOD_NAME( NAME ) _callVarArgsMethod__##NAME #define PYCXX_KEYWORDS_METHOD_NAME( NAME ) _callKeywordsMethod__##NAME #define PYCXX_NOARGS_METHOD_DECL( CLS, NAME ) \ static PyObject *PYCXX_NOARGS_METHOD_NAME( NAME )( PyObject *_self, PyObject *, PyObject * ) \ { \ try \ { \ Py::PythonClassInstance *self_python = reinterpret_cast< Py::PythonClassInstance * >( _self ); \ CLS *self = reinterpret_cast< CLS * >( self_python->m_pycxx_object ); \ Py::Object r( (self->NAME)() ); \ return Py::new_reference_to( r.ptr() ); \ } \ catch( Py::Exception & ) \ { \ return 0; \ } \ } #define PYCXX_VARARGS_METHOD_DECL( CLS, NAME ) \ static PyObject *PYCXX_VARARGS_METHOD_NAME( NAME )( PyObject *_self, PyObject *_a, PyObject * ) \ { \ try \ { \ Py::PythonClassInstance *self_python = reinterpret_cast< Py::PythonClassInstance * >( _self ); \ CLS *self = reinterpret_cast< CLS * >( self_python->m_pycxx_object ); \ Py::Tuple a( _a ); \ Py::Object r( (self->NAME)( a ) ); \ return Py::new_reference_to( r.ptr() ); \ } \ catch( Py::Exception & ) \ { \ return 0; \ } \ } #define PYCXX_KEYWORDS_METHOD_DECL( CLS, NAME ) \ static PyObject *PYCXX_KEYWORDS_METHOD_NAME( NAME )( PyObject *_self, PyObject *_a, PyObject *_k ) \ { \ try \ { \ Py::PythonClassInstance *self_python = reinterpret_cast< Py::PythonClassInstance * >( _self ); \ CLS *self = reinterpret_cast< CLS * >( self_python->m_pycxx_object ); \ Py::Tuple a( _a ); \ Py::Dict k; \ if( _k != NULL ) \ k = _k; \ Py::Object r( (self->NAME)( a, k ) ); \ return Py::new_reference_to( r.ptr() ); \ } \ catch( Py::Exception & ) \ { \ return 0; \ } \ } // need to support METH_STATIC and METH_CLASS #define PYCXX_ADD_NOARGS_METHOD( PYNAME, NAME, docs ) \ add_method( #PYNAME, (PyCFunction)PYCXX_NOARGS_METHOD_NAME( NAME ), METH_NOARGS, docs ) #define PYCXX_ADD_VARARGS_METHOD( PYNAME, NAME, docs ) \ add_method( #PYNAME, (PyCFunction)PYCXX_VARARGS_METHOD_NAME( NAME ), METH_VARARGS, docs ) #define PYCXX_ADD_KEYWORDS_METHOD( PYNAME, NAME, docs ) \ add_method( #PYNAME, (PyCFunction)PYCXX_KEYWORDS_METHOD_NAME( NAME ), METH_VARARGS | METH_KEYWORDS, docs ) namespace Py { extern PythonExtensionBase *getPythonExtensionBase( PyObject *self ); struct PythonClassInstance { PyObject_HEAD PythonExtensionBase *m_pycxx_object; }; class ExtensionClassMethodsTable { public: ExtensionClassMethodsTable() : m_methods_table( new PyMethodDef[ METHOD_TABLE_SIZE_INCREMENT ] ) , m_methods_used( 0 ) , m_methods_size( METHOD_TABLE_SIZE_INCREMENT ) { } ~ExtensionClassMethodsTable() { delete m_methods_table; } // check that all methods added are unique void check_unique_method_name( const char *_name ) { std::string name( _name ); for( int i=0; iml_name = name; p->ml_meth = function; p->ml_flags = flags; p->ml_doc = doc; m_methods_used++; p++; // add the sentinel marking the table end p->ml_name = NULL; p->ml_meth = NULL; p->ml_flags = 0; p->ml_doc = NULL; return m_methods_table; } private: enum {METHOD_TABLE_SIZE_INCREMENT = 1}; PyMethodDef *m_methods_table; int m_methods_used; int m_methods_size; }; template class PythonClass : public PythonExtensionBase { protected: explicit PythonClass( PythonClassInstance *self, Tuple &args, Dict &kwds ) : PythonExtensionBase() , m_class_instance( self ) { } virtual ~PythonClass() {} static ExtensionClassMethodsTable &methodTable() { static ExtensionClassMethodsTable *method_table; if( method_table == NULL ) method_table = new ExtensionClassMethodsTable; return *method_table; } static void add_method( const char *name, PyCFunction function, int flags, const char *doc=NULL ) { behaviors().set_methods( methodTable().add_method( name, function, flags, doc ) ); } static PythonType &behaviors() { static PythonType *p; if( p == NULL ) { #if defined( _CPPRTTI ) || defined( __GNUG__ ) const char *default_name = (typeid( T )).name(); #else const char *default_name = "unknown"; #endif p = new PythonType( sizeof( T ), 0, default_name ); p->set_tp_new( extension_object_new ); p->set_tp_init( extension_object_init ); p->set_tp_dealloc( extension_object_deallocator ); // we are a class p->supportClass(); // always support get and set attr p->supportGetattro(); p->supportSetattro(); } return *p; } static PyObject *extension_object_new( PyTypeObject *subtype, PyObject *args, PyObject *kwds ) { #ifdef PYCXX_DEBUG std::cout << "extension_object_new()" << std::endl; #endif PythonClassInstance *o = reinterpret_cast( subtype->tp_alloc( subtype, 0 ) ); if( o == NULL ) return NULL; o->m_pycxx_object = NULL; PyObject *self = reinterpret_cast( o ); #ifdef PYCXX_DEBUG std::cout << "extension_object_new() => self=0x" << std::hex << reinterpret_cast< unsigned int >( self ) << std::dec << std::endl; #endif return self; } static int extension_object_init( PyObject *_self, PyObject *args_, PyObject *kwds_ ) { try { Py::Tuple args( args_ ); Py::Dict kwds; if( kwds_ != NULL ) kwds = kwds_; PythonClassInstance *self = reinterpret_cast( _self ); #ifdef PYCXX_DEBUG std::cout << "extension_object_init( self=0x" << std::hex << reinterpret_cast< unsigned int >( self ) << std::dec << " )" << std::endl; std::cout << " self->m_pycxx_object=0x" << std::hex << reinterpret_cast< unsigned int >( self->m_pycxx_object ) << std::dec << std::endl; #endif if( self->m_pycxx_object == NULL ) { self->m_pycxx_object = new T( self, args, kwds ); #ifdef PYCXX_DEBUG std::cout << " self->m_pycxx_object=0x" << std::hex << reinterpret_cast< unsigned int >( self->m_pycxx_object ) << std::dec << std::endl; #endif } else { #ifdef PYCXX_DEBUG std::cout << " reinit - self->m_pycxx_object=0x" << std::hex << reinterpret_cast< unsigned int >( self->m_pycxx_object ) << std::dec << std::endl; #endif self->m_pycxx_object->reinit( args, kwds ); } } catch( Exception & ) { return -1; } return 0; } static void extension_object_deallocator( PyObject *_self ) { PythonClassInstance *self = reinterpret_cast< PythonClassInstance * >( _self ); #ifdef PYCXX_DEBUG std::cout << "extension_object_deallocator( self=0x" << std::hex << reinterpret_cast< unsigned int >( self ) << std::dec << " )" << std::endl; std::cout << " self->m_pycxx_object=0x" << std::hex << reinterpret_cast< unsigned int >( self->m_pycxx_object ) << std::dec << std::endl; #endif delete self->m_pycxx_object; _self->ob_type->tp_free( _self ); } public: static PyTypeObject *type_object() { return behaviors().type_object(); } static Object type() { return Object( reinterpret_cast( behaviors().type_object() ) ); } static bool check( PyObject *p ) { // is p like me? return p->ob_type == type_object(); } static bool check( const Object &ob ) { return check( ob.ptr() ); } virtual PyObject *selfPtr() { return reinterpret_cast( m_class_instance ); } virtual Object self() { return Object( reinterpret_cast( m_class_instance ) ); } protected: private: PythonClassInstance *m_class_instance; private: // // prevent the compiler generating these unwanted functions // explicit PythonClass( const PythonClass &other ); void operator=( const PythonClass &rhs ); }; // // ExtensionObject is an Object that will accept only T's. // template class PythonClassObject: public Object { public: explicit PythonClassObject( PyObject *pyob ) : Object( pyob ) { validate(); } PythonClassObject( const PythonClassObject &other ) : Object( *other ) { validate(); } PythonClassObject( const Object &other ) : Object( *other ) { validate(); } PythonClassObject &operator=( const Object &rhs ) { *this = *rhs; return *this; } PythonClassObject &operator=( PyObject *rhsp ) { if( ptr() != rhsp ) set( rhsp ); return *this; } virtual bool accepts( PyObject *pyob ) const { return( pyob && T::check( pyob ) ); } // // Obtain a pointer to the PythonExtension object // T *getCxxObject( void ) { return dynamic_cast< T * >( getPythonExtensionBase( ptr() ) ); } }; } // Namespace Py // End of __CXX_ExtensionClass__h #endif pycxx-6.2.5/CXX/Python3/ExtensionTypeBase.hxx000644 000771 000000 00000017552 12160124644 021333 0ustar00barrywheel000000 000000 //----------------------------------------------------------------------------- // // Copyright (c) 1998 - 2007, The Regents of the University of California // Produced at the Lawrence Livermore National Laboratory // All rights reserved. // // This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The // full copyright notice is contained in the file COPYRIGHT located at the root // of the PyCXX distribution. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // - Redistributions of source code must retain the above copyright notice, // this list of conditions and the disclaimer below. // - Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the disclaimer (as noted below) in the // documentation and/or materials provided with the distribution. // - Neither the name of the UC/LLNL nor the names of its contributors may be // used to endorse or promote products derived from this software without // specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF // CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH // DAMAGE. // //----------------------------------------------------------------------------- #ifndef __CXX_ExtensionTypeBase__h #define __CXX_ExtensionTypeBase__h namespace Py { // Class PythonExtension is what you inherit from to create // a new Python extension type. You give your class itself // as the template paramter. // There are two ways that extension objects can get destroyed. // 1. Their reference count goes to zero // 2. Someone does an explicit delete on a pointer. // In(1) the problem is to get the destructor called // We register a special deallocator in the Python type object // (see behaviors()) to do this. // In(2) there is no problem, the dtor gets called. // PythonExtension does not use the usual Python heap allocator, // instead using new/delete. We do the setting of the type object // and reference count, usually done by PyObject_New, in the // base class ctor. // This special deallocator does a delete on the pointer. class PythonExtensionBase : public PyObject { public: PythonExtensionBase(); virtual ~PythonExtensionBase(); public: // object virtual void reinit( Tuple &args, Dict &kwds ); // object basics #ifdef PYCXX_PYTHON_2TO3 virtual int print( FILE *, int ); #endif virtual Object getattr( const char * ); virtual int setattr( const char *, const Object & ); virtual Object getattro( const String & ); Object genericGetAttro( const String & ); virtual int setattro( const String &, const Object & ); int genericSetAttro( const String &, const Object & ); virtual int compare( const Object & ); virtual Object rich_compare( const Object &, int ); virtual Object repr(); virtual Object str(); virtual long hash(); virtual Object call( const Object &, const Object & ); virtual Object iter(); virtual PyObject *iternext(); // Sequence methods virtual int sequence_length(); virtual Object sequence_concat( const Object & ); virtual Object sequence_repeat( Py_ssize_t ); virtual Object sequence_item( Py_ssize_t ); virtual int sequence_ass_item( Py_ssize_t, const Object & ); // Mapping virtual int mapping_length(); virtual Object mapping_subscript( const Object & ); virtual int mapping_ass_subscript( const Object &, const Object & ); // Number virtual Object number_negative(); virtual Object number_positive(); virtual Object number_absolute(); virtual Object number_invert(); virtual Object number_int(); virtual Object number_float(); virtual Object number_long(); virtual Object number_add( const Object & ); virtual Object number_subtract( const Object & ); virtual Object number_multiply( const Object & ); virtual Object number_remainder( const Object & ); virtual Object number_divmod( const Object & ); virtual Object number_lshift( const Object & ); virtual Object number_rshift( const Object & ); virtual Object number_and( const Object & ); virtual Object number_xor( const Object & ); virtual Object number_or( const Object & ); virtual Object number_power( const Object &, const Object & ); // Buffer virtual int buffer_get( Py_buffer *, int flags ); virtual int buffer_release( Py_buffer *buf ); public: // helper functions to call function fn_name with 0 to 9 args Object callOnSelf( const std::string &fn_name ); Object callOnSelf( const std::string &fn_name, const Object &arg1 ); Object callOnSelf( const std::string &fn_name, const Object &arg1, const Object &arg2 ); Object callOnSelf( const std::string &fn_name, const Object &arg1, const Object &arg2, const Object &arg3 ); Object callOnSelf( const std::string &fn_name, const Object &arg1, const Object &arg2, const Object &arg3, const Object &arg4 ); Object callOnSelf( const std::string &fn_name, const Object &arg1, const Object &arg2, const Object &arg3, const Object &arg4, const Object &arg5 ); Object callOnSelf( const std::string &fn_name, const Object &arg1, const Object &arg2, const Object &arg3, const Object &arg4, const Object &arg5, const Object &arg6 ); Object callOnSelf( const std::string &fn_name, const Object &arg1, const Object &arg2, const Object &arg3, const Object &arg4, const Object &arg5, const Object &arg6, const Object &arg7 ); Object callOnSelf( const std::string &fn_name, const Object &arg1, const Object &arg2, const Object &arg3, const Object &arg4, const Object &arg5, const Object &arg6, const Object &arg7, const Object &arg8 ); Object callOnSelf( const std::string &fn_name, const Object &arg1, const Object &arg2, const Object &arg3, const Object &arg4, const Object &arg5, const Object &arg6, const Object &arg7, const Object &arg8, const Object &arg9 ); public: virtual PyObject *selfPtr() = 0; virtual Object self() = 0; private: void missing_method( void ); static PyObject *method_call_handler( PyObject *self, PyObject *args ); }; } // Namespace Py // End of __CXX_ExtensionTypeBase__h #endif pycxx-6.2.5/CXX/Python3/IndirectPythonInterface.hxx000644 000771 000000 00000012567 11541734710 022512 0ustar00barrywheel000000 000000 //----------------------------------------------------------------------------- // // Copyright (c) 1998 - 2007, The Regents of the University of California // Produced at the Lawrence Livermore National Laboratory // All rights reserved. // // This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The // full copyright notice is contained in the file COPYRIGHT located at the root // of the PyCXX distribution. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // - Redistributions of source code must retain the above copyright notice, // this list of conditions and the disclaimer below. // - Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the disclaimer (as noted below) in the // documentation and/or materials provided with the distribution. // - Neither the name of the UC/LLNL nor the names of its contributors may be // used to endorse or promote products derived from this software without // specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF // CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH // DAMAGE. // //----------------------------------------------------------------------------- #ifndef __CXX_INDIRECT_PYTHON_INTERFACE__HXX__ #define __CXX_INDIRECT_PYTHON_INTERFACE__HXX__ #include "CXX/WrapPython.h" namespace Py { bool InitialisePythonIndirectInterface(); // // Wrap Exception variables as function calls // PyObject * _Exc_Exception(); PyObject * _Exc_StandardError(); PyObject * _Exc_ArithmeticError(); PyObject * _Exc_LookupError(); PyObject * _Exc_AssertionError(); PyObject * _Exc_AttributeError(); PyObject * _Exc_EOFError(); PyObject * _Exc_FloatingPointError(); PyObject * _Exc_EnvironmentError(); PyObject * _Exc_IOError(); PyObject * _Exc_OSError(); PyObject * _Exc_ImportError(); PyObject * _Exc_IndexError(); PyObject * _Exc_KeyError(); PyObject * _Exc_KeyboardInterrupt(); PyObject * _Exc_MemoryError(); PyObject * _Exc_NameError(); PyObject * _Exc_OverflowError(); PyObject * _Exc_RuntimeError(); PyObject * _Exc_NotImplementedError(); PyObject * _Exc_SyntaxError(); PyObject * _Exc_SystemError(); PyObject * _Exc_SystemExit(); PyObject * _Exc_TypeError(); PyObject * _Exc_ValueError(); PyObject * _Exc_ZeroDivisionError(); #ifdef MS_WINDOWS PyObject * _Exc_WindowsError(); #endif PyObject * _Exc_IndentationError(); PyObject * _Exc_TabError(); PyObject * _Exc_UnboundLocalError(); PyObject * _Exc_UnicodeError(); // // Wrap Object variables as function calls // PyObject * _None(); PyObject * _False(); PyObject * _True(); // // Wrap Type variables as function calls // PyTypeObject * _List_Type(); bool _List_Check( PyObject *o ); PyTypeObject * _Buffer_Type(); bool _Buffer_Check( PyObject *op ); PyTypeObject * _Class_Type(); bool _Class_Check( PyObject *op ); PyTypeObject * _Instance_Type(); bool _Instance_Check( PyObject *op ); PyTypeObject * _Method_Type(); bool _Method_Check( PyObject *op ); PyTypeObject * _Complex_Type(); bool _Complex_Check( PyObject *op ); PyTypeObject * _Dict_Type(); bool _Dict_Check( PyObject *op ); PyTypeObject * _File_Type(); bool _File_Check( PyObject *op ); PyTypeObject * _Float_Type(); bool _Float_Check( PyObject *op ); PyTypeObject * _Frame_Type(); bool _Frame_Check( PyObject *op ); PyTypeObject * _Function_Type(); bool _Function_Check( PyObject *op ); PyTypeObject * _Bool_Type(); bool _Boolean_Check( PyObject *op ); PyTypeObject * _Int_Type(); bool _Int_Check( PyObject *op ); PyTypeObject * _List_Type(); bool _List_Check( PyObject *op ); PyTypeObject * _Long_Type(); bool _Long_Check( PyObject *op ); PyTypeObject * _CFunction_Type(); bool _CFunction_Check( PyObject *op ); PyTypeObject * _Module_Type(); bool _Module_Check( PyObject *op ); PyTypeObject * _Type_Type(); bool _Type_Check( PyObject *op ); PyTypeObject * _Range_Type(); bool _Range_Check( PyObject *op ); PyTypeObject * _Slice_Type(); bool _Slice_Check( PyObject *op ); PyTypeObject * _Unicode_Type(); bool _Unicode_Check( PyObject *op ); PyTypeObject * _Bytes_Type(); bool _Bytes_Check( PyObject *op ); PyTypeObject * _TraceBack_Type(); bool _TraceBack_Check( PyObject *v ); PyTypeObject * _Tuple_Type(); bool _Tuple_Check( PyObject *op ); int &_Py_DebugFlag(); int &_Py_InteractiveFlag(); int &_Py_OptimizeFlag(); int &_Py_NoSiteFlag(); int &_Py_TabcheckFlag(); int &_Py_VerboseFlag(); int &_Py_UnicodeFlag(); void _XINCREF( PyObject *op ); void _XDECREF( PyObject *op ); char *__Py_PackageContext(); }; #endif // __CXX_INDIRECT_PYTHON_INTERFACE__HXX__ pycxx-6.2.5/CXX/Python3/Objects.hxx000644 000771 000000 00000264413 11724120210 017301 0ustar00barrywheel000000 000000 //----------------------------------------------------------------------------- // // Copyright (c) 1998 - 2007, The Regents of the University of California // Produced at the Lawrence Livermore National Laboratory // All rights reserved. // // This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The // full copyright notice is contained in the file COPYRIGHT located at the root // of the PyCXX distribution. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // - Redistributions of source code must retain the above copyright notice, // this list of conditions and the disclaimer below. // - Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the disclaimer (as noted below) in the // documentation and/or materials provided with the distribution. // - Neither the name of the UC/LLNL nor the names of its contributors may be // used to endorse or promote products derived from this software without // specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF // CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH // DAMAGE. // //----------------------------------------------------------------------------- #ifndef __CXX_Objects__h #define __CXX_Objects__h #include "CXX/WrapPython.h" #include "CXX/Version.hxx" #include "CXX/Python3/Config.hxx" #include "CXX/Python3/CxxDebug.hxx" #include "CXX/Python3/Exception.hxx" #include #include STR_STREAM #include #include #include #include namespace Py { typedef int sequence_index_type; // type of an index into a sequence // Forward declarations class Object; class Type; template class SeqBase; class Bytes; class String; class List; template class MapBase; class Tuple; class Dict; //===========================================================================// // class Object // The purpose of this class is to serve as the most general kind of // Python object, for the purpose of writing C++ extensions in Python // Objects hold a PyObject* which they own. This pointer is always a // valid pointer to a Python object. In children we must maintain this behavior. // // Instructions on how to make your own class MyType descended from Object: // (0) Pick a base class, either Object or perhaps SeqBase or MapBase. // This example assumes Object. // (1) Write a routine int MyType_Check( PyObject * ) modeled after PyInt_Check, // PyFloat_Check, etc. // (2) Add method accepts: // virtual bool accepts( PyObject *pyob ) const { // return pyob && MyType_Check( pyob ); // } // (3) Include the following constructor and copy constructor // /* explicit MyType( PyObject *pyob ): Object( pyob ) { validate(); } MyType( const Object &other ): Object( other.ptr() ) { validate(); } */ // Alernate version for the constructor to allow for construction from owned pointers: /* explicit MyType( PyObject *pyob ): Object( pyob ) { validate(); } */ // You may wish to add other constructors; see the classes below for examples. // Each constructor must use "set" to set the pointer // and end by validating the pointer you have created. //( 4 ) Each class needs at least these two assignment operators: /* MyType &operator=( const Object &rhs ) { return *this = *rhs; } Mytype &operator=( PyObject *rhsp ) { if( ptr() != rhsp ) set( rhsp ); return *this; } */ // Note on accepts: constructors call the base class // version of a virtual when calling the base class constructor, // so the test has to be done explicitly in a descendent. // If you are inheriting from PythonExtension to define an object // note that it contains PythonExtension::check // which you can use in accepts when writing a wrapper class. // See Demo/range.h and Demo/range.cxx for an example. class Object { private: // the pointer to the Python object // Only Object sets this directly. // The default constructor for Object sets it to Py_None and // child classes must use "set" to set it // PyObject *p; protected: void set( PyObject *pyob, bool owned = false ) { release(); p = pyob; if( !owned ) { Py::_XINCREF( p ); } validate(); } void release() { Py::_XDECREF( p ); p = NULL; } void validate(); public: // Constructor acquires new ownership of pointer unless explicitly told not to. explicit Object( PyObject *pyob=Py::_None(), bool owned = false ) : p( pyob ) { if( !owned ) { Py::_XINCREF( p ); } validate(); } // Copy constructor acquires new ownership of pointer Object( const Object &ob ) : p( ob.p ) { Py::_XINCREF( p ); validate(); } // Assignment acquires new ownership of pointer Object &operator=( const Object &rhs ) { set( rhs.p ); return *this; } Object &operator=( PyObject *rhsp ) { if( ptr() != rhsp ) set( rhsp ); return *this; } // Destructor virtual ~Object() { release(); } // Loaning the pointer to others, retain ownership PyObject *operator*() const { return p; } // Explicit reference_counting changes void increment_reference_count() { Py::_XINCREF( p ); } void decrement_reference_count() { // not allowed to commit suicide, however if( reference_count() == 1 ) throw RuntimeError( "Object::decrement_reference_count error." ); Py::_XDECREF( p ); } // Would like to call this pointer() but messes up STL in SeqBase PyObject *ptr() const { return p; } // // Queries // // Can pyob be used in this object's constructor? virtual bool accepts( PyObject *pyob ) const { // allow any object or NULL return true; } Py_ssize_t reference_count() const { // the reference count return p ? p->ob_refcnt : 0; } Type type() const; // the type object associated with this one String str() const; // the str() representation std::string as_string() const; String repr() const; // the repr() representation List dir() const; // the dir() list bool hasAttr( const std::string &s ) const { return PyObject_HasAttrString( p, const_cast( s.c_str() ) ) ? true: false; } Object getAttr( const std::string &s ) const { return Object( PyObject_GetAttrString( p, const_cast( s.c_str() ) ), true ); } Object callMemberFunction( const std::string &function_name ) const; Object callMemberFunction( const std::string &function_name, const Tuple &args ) const; Object callMemberFunction( const std::string &function_name, const Tuple &args, const Dict &kw ) const; Object getItem( const Object &key ) const { return Object( PyObject_GetItem( p, *key ), true ); } long hashValue() const { return PyObject_Hash( p ); } // convert to bool bool as_bool() const { return PyObject_IsTrue( ptr() ) != 0; } //operator bool() const //{ // return as_bool(); //} // int print( FILE *fp, int flags=Py_Print_RAW ) //{ // return PyObject_Print( p, fp, flags ); //} bool is( PyObject *pother ) const { // identity test return p == pother; } bool is( const Object &other ) const { // identity test return p == other.p; } bool isNull() const { return p == NULL; } bool isNone() const { return p == _None(); } bool isCallable() const { return PyCallable_Check( p ) != 0; } bool isDict() const { return Py::_Dict_Check( p ); } bool isList() const { return Py::_List_Check( p ); } bool isMapping() const { return PyMapping_Check( p ) != 0; } bool isNumeric() const { return PyNumber_Check( p ) != 0; } bool isSequence() const { return PySequence_Check( p ) != 0; } bool isTrue() const { return PyObject_IsTrue( p ) != 0; } bool isType( const Type &t ) const; bool isTuple() const { return Py::_Tuple_Check( p ); } bool isString() const { return Py::_Unicode_Check( p ); } bool isBytes() const { return Py::_Bytes_Check( p ); } bool isBoolean() const { return Py::_Boolean_Check( p ); } // Commands void setAttr( const std::string &s, const Object &value ) { if( PyObject_SetAttrString( p, const_cast( s.c_str() ), *value ) == -1 ) throw AttributeError( "getAttr failed." ); } void delAttr( const std::string &s ) { if( PyObject_DelAttrString( p, const_cast( s.c_str() ) ) == -1 ) throw AttributeError( "delAttr failed." ); } // PyObject_SetItem is too weird to be using from C++ // so it is intentionally omitted. void delItem( const Object &key ) { //if( PyObject_DelItem( p, *key ) == -1 ) // failed to link on Windows? throw KeyError( "delItem failed." ); } // Equality and comparison use PyObject_Compare }; // End of class Object // Null can be return from when it is require to return NULL to Python from a method class Null: public Object { public: Null() : Object( NULL ) { } virtual ~Null() { } virtual bool accepts( PyObject *pyob ) { return pyob == NULL; } }; //------------------------------------------------------------ bool operator==( const Object &o1, const Object &o2 ); bool operator!=( const Object &o1, const Object &o2 ); bool operator>=( const Object &o1, const Object &o2 ); bool operator<=( const Object &o1, const Object &o2 ); bool operator<( const Object &o1, const Object &o2 ); bool operator>( const Object &o1, const Object &o2 ); //------------------------------------------------------------ // // Convert an owned Python pointer into a PyCXX Object // inline Object asObject( PyObject *p ) { return Object( p, true ); } // new_reference_to also overloaded below on Object inline PyObject *new_reference_to( PyObject *p ) { Py::_XINCREF( p ); return p; } inline PyObject *new_reference_to( const Object &g ) { PyObject *p = g.ptr(); Py::_XINCREF( p ); return p; } // Python special None value inline Object None() { return Object( Py::_None() ); } // Python special Boolean values inline Object False() { return Object( Py::_False() ); } inline Object True() { return Object( Py::_True() ); } // TMM: 31May'01 - Added the #ifndef so I can exlude iostreams. #ifndef CXX_NO_IOSTREAMS std::ostream &operator<<( std::ostream &os, const Object &ob ); #endif // Class Type class Type: public Object { public: explicit Type( PyObject *pyob, bool owned = false ) : Object( pyob, owned ) { validate(); } Type( const Object &ob ) : Object( *ob ) { validate(); } Type( const Type &t ) : Object( t ) { validate(); } Type &operator=( const Object &rhs ) { return *this = *rhs; } Type &operator=( PyObject *rhsp ) { if( ptr() != rhsp ) set( rhsp ); return *this; } virtual bool accepts( PyObject *pyob ) const { return pyob && Py::_Type_Check( pyob ); } }; // =============================================== // class boolean class Boolean: public Object { public: // Constructor Boolean( PyObject *pyob, bool owned = false ) : Object( pyob, owned ) { validate(); } Boolean( const Boolean &ob ) : Object( *ob ) { validate(); } // create from bool Boolean( bool v=false ) { set( PyBool_FromLong( v ? 1 : 0 ), true ); validate(); } explicit Boolean( const Object &ob ) : Object( *ob ) { validate(); } // Assignment acquires new ownership of pointer Boolean &operator=( const Object &rhs ) { return *this = *rhs; } Boolean &operator=( PyObject *rhsp ) { if( ptr() != rhsp ) set( rhsp ); return *this; } // Membership virtual bool accepts( PyObject *pyob ) const { // accepts any object that can be converted to a boolean return pyob && PyObject_IsTrue( pyob ) != -1; } Boolean &operator=( bool v ) { set( PyBool_FromLong( v ? 1 : 0 ), true ); return *this; } operator bool() const { return as_bool(); } }; // =============================================== // class Long class Long: public Object { public: // Constructor explicit Long( PyObject *pyob, bool owned = false ) : Object( pyob, owned ) { validate(); } Long( const Long &ob ) : Object( ob.ptr() ) { validate(); } // try to create from any object explicit Long( const Object &ob ) : Object( PyNumber_Long( *ob ), true ) { validate(); } // create from long explicit Long( long v = 0L ) : Object( PyLong_FromLong( v ), true ) { validate(); } // create from unsigned long explicit Long( unsigned long v ) : Object( PyLong_FromUnsignedLong( v ), true ) { validate(); } // create from int explicit Long( int v ) : Object( PyLong_FromLong( static_cast( v ) ), true ) { validate(); } #ifdef HAVE_LONG_LONG // create from long long explicit Long( PY_LONG_LONG v ) : Object( PyLong_FromLongLong( v ), true ) { validate(); } // create from unsigned long long explicit Long( unsigned PY_LONG_LONG v ) : Object( PyLong_FromUnsignedLongLong( v ), true ) { validate(); } #endif // Membership virtual bool accepts( PyObject *pyob ) const { return pyob && Py::_Long_Check( pyob ); } // Assignment acquires new ownership of pointer Long &operator=( const Object &rhs ) { return *this = *rhs; } Long &operator=( PyObject *rhsp ) { if( ptr() != rhsp ) set( PyNumber_Long( rhsp ), true ); return *this; } // assign from an int Long &operator=( int v ) { set( PyLong_FromLong( long( v ) ), true ); return *this; } // assign from long Long &operator=( long v ) { set( PyLong_FromLong( v ), true ); return *this; } // assign from unsigned long Long &operator=( unsigned long v ) { set( PyLong_FromUnsignedLong( v ), true ); return *this; } #ifdef HAVE_LONG_LONG Long &operator=( PY_LONG_LONG v ) { set( PyLong_FromLongLong( v ), true ); return *this; } Long &operator=( unsigned PY_LONG_LONG v ) { set( PyLong_FromUnsignedLongLong( v ), true ); return *this; } #endif //operator bool() const //{ // return as_bool(); //} // convert to long long as_long() const { return PyLong_AsLong( ptr() ); } operator long() const { return as_long(); } operator int() const { return static_cast( as_long() ); } // convert to unsigned long as_unsigned_long() const { return PyLong_AsUnsignedLong( ptr() ); } operator unsigned long() const { return as_unsigned_long(); } double as_double() const { return PyLong_AsDouble( ptr() ); } operator double() const { return as_double(); } #ifdef HAVE_LONG_LONG PY_LONG_LONG as_long_long() const { return PyLong_AsLongLong( ptr() ); } operator PY_LONG_LONG() const { return as_long_long(); } unsigned PY_LONG_LONG as_unsigned_long_long() const { return PyLong_AsUnsignedLongLong( ptr() ); } operator unsigned PY_LONG_LONG() const { return as_unsigned_long_long(); } #endif // prefix ++ Long operator++() { set( PyNumber_Add( ptr(), *Long( 1 ) ) ); return *this; } // postfix ++ Long operator++( int ) { Long a = *this; set( PyNumber_Add( ptr(), *Long( 1 ) ) ); return a; } // prefix -- Long operator--() { set( PyNumber_Subtract( ptr(), *Long( 1 ) ) ); return *this; } // postfix -- Long operator--( int ) { Long a = *this; set( PyNumber_Subtract( ptr(), *Long( 1 ) ) ); return a; } }; #ifdef PYCXX_PYTHON_2TO3 // PyCXX for Python2 had an Int and LongLong classes typedef Long Int; #ifdef HAVE_LONG_LONG typedef Long LongLong; #endif #endif #if 1 //------------------------------------------------------------ // compare operators bool operator!=( const Long &a, const Long &b ); bool operator!=( const Long &a, int b ); bool operator!=( const Long &a, long b ); bool operator!=( int a, const Long &b ); bool operator!=( long a, const Long &b ); //------------------------------ bool operator==( const Long &a, const Long &b ); bool operator==( const Long &a, int b ); bool operator==( const Long &a, long b ); bool operator==( int a, const Long &b ); bool operator==( long a, const Long &b ); //------------------------------ bool operator>( const Long &a, const Long &b ); bool operator>( const Long &a, int b ); bool operator>( const Long &a, long b ); bool operator>( int a, const Long &b ); bool operator>( long a, const Long &b ); //------------------------------ bool operator>=( const Long &a, const Long &b ); bool operator>=( const Long &a, int b ); bool operator>=( const Long &a, long b ); bool operator>=( int a, const Long &b ); bool operator>=( long a, const Long &b ); //------------------------------ bool operator<( const Long &a, const Long &b ); bool operator<( const Long &a, int b ); bool operator<( const Long &a, long b ); bool operator<( int a, const Long &b ); bool operator<( long a, const Long &b ); //------------------------------ bool operator<=( const Long &a, const Long &b ); bool operator<=( int a, const Long &b ); bool operator<=( long a, const Long &b ); bool operator<=( const Long &a, int b ); bool operator<=( const Long &a, long b ); #ifdef HAVE_LONG_LONG //------------------------------ bool operator!=( const Long &a, PY_LONG_LONG b ); bool operator!=( PY_LONG_LONG a, const Long &b ); //------------------------------ bool operator==( const Long &a, PY_LONG_LONG b ); bool operator==( PY_LONG_LONG a, const Long &b ); //------------------------------ bool operator>( const Long &a, PY_LONG_LONG b ); bool operator>( PY_LONG_LONG a, const Long &b ); //------------------------------ bool operator>=( const Long &a, PY_LONG_LONG b ); bool operator>=( PY_LONG_LONG a, const Long &b ); //------------------------------ bool operator<( const Long &a, PY_LONG_LONG b ); bool operator<( PY_LONG_LONG a, const Long &b ); //------------------------------ bool operator<=( const Long &a, PY_LONG_LONG b ); bool operator<=( PY_LONG_LONG a, const Long &b ); #endif #endif // =============================================== // class Float // class Float: public Object { public: // Constructor explicit Float( PyObject *pyob, bool owned = false ) : Object( pyob, owned ) { validate(); } Float( const Float &f ) : Object( f ) { validate(); } // make from double explicit Float( double v=0.0 ) : Object( PyFloat_FromDouble( v ), true ) { validate(); } // try to make from any object Float( const Object &ob ) : Object( PyNumber_Float( *ob ), true ) { validate(); } Float &operator=( const Object &rhs ) { return *this = *rhs; } Float &operator=( PyObject *rhsp ) { if( ptr() != rhsp ) set( PyNumber_Float( rhsp ), true ); return *this; } // Membership virtual bool accepts( PyObject *pyob ) const { return pyob && Py::_Float_Check( pyob ); } double as_double() const { return PyFloat_AsDouble( ptr() ); } // convert to double operator double() const { return as_double(); } // assign from a double Float &operator=( double v ) { set( PyFloat_FromDouble( v ), true ); return *this; } // assign from an int Float &operator=( int v ) { set( PyFloat_FromDouble( double( v ) ), true ); return *this; } // assign from long Float &operator=( long v ) { set( PyFloat_FromDouble( double( v ) ), true ); return *this; } // assign from an Long Float &operator=( const Long &iob ) { set( PyFloat_FromDouble( double( iob.as_long() ) ), true ); return *this; } }; //------------------------------------------------------------ // compare operators bool operator!=( const Float &a, const Float &b ); bool operator!=( const Float &a, double b ); bool operator!=( double a, const Float &b ); //------------------------------ bool operator==( const Float &a, const Float &b ); bool operator==( const Float &a, double b ); bool operator==( double a, const Float &b ); //------------------------------ bool operator>( const Float &a, const Float &b ); bool operator>( const Float &a, double b ); bool operator>( double a, const Float &b ); //------------------------------ bool operator>=( const Float &a, const Float &b ); bool operator>=( const Float &a, double b ); bool operator>=( double a, const Float &b ); //------------------------------ bool operator<( const Float &a, const Float &b ); bool operator<( const Float &a, double b ); bool operator<( double a, const Float &b ); //------------------------------ bool operator<=( const Float &a, const Float &b ); bool operator<=( double a, const Float &b ); bool operator<=( const Float &a, double b ); // =============================================== // class Complex class Complex: public Object { public: // Constructor explicit Complex( PyObject *pyob, bool owned = false ) : Object( pyob, owned ) { validate(); } Complex( const Complex &f ) : Object( f ) { validate(); } // make from double explicit Complex( double v=0.0, double w=0.0 ) :Object( PyComplex_FromDoubles( v, w ), true ) { validate(); } Complex &operator=( const Object &rhs ) { return *this = *rhs; } Complex &operator=( PyObject *rhsp ) { if( ptr() != rhsp ) set( rhsp ); return *this; } // Membership virtual bool accepts( PyObject *pyob ) const { return pyob && Py::_Complex_Check( pyob ); } // convert to Py_complex operator Py_complex() const { return PyComplex_AsCComplex( ptr() ); } // assign from a Py_complex Complex &operator=( const Py_complex &v ) { set( PyComplex_FromCComplex( v ), true ); return *this; } // assign from a double Complex &operator=( double v ) { set( PyComplex_FromDoubles( v, 0.0 ), true ); return *this; } // assign from an int Complex &operator=( int v ) { set( PyComplex_FromDoubles( double( v ), 0.0 ), true ); return *this; } // assign from long Complex &operator=( long v ) { set( PyComplex_FromDoubles( double( v ), 0.0 ), true ); return *this; } // assign from an Long Complex &operator=( const Long &iob ) { set( PyComplex_FromDoubles( double( iob.as_long() ), 0.0 ), true ); return *this; } double real() const { return PyComplex_RealAsDouble( ptr() ); } double imag() const { return PyComplex_ImagAsDouble( ptr() ); } }; // Sequences // Sequences are here represented as sequences of items of type T. // The base class SeqBase represents that. // In basic Python T is always "Object". // seqref is what you get if you get elements from a non-const SeqBase. // Note: seqref could probably be a nested class in SeqBase but that might stress // some compilers needlessly. Simlarly for mapref later. // While this class is not intended for enduser use, it needs some public // constructors for the benefit of the STL. // See Scott Meyer's More Essential C++ for a description of proxies. // This application is even more complicated. We are doing an unusual thing // in having a double proxy. If we want the STL to work // properly we have to compromise by storing the rvalue inside. The // entire Object API is repeated so that things like s[i].isList() will // work properly. // Still, once in a while a weird compiler message may occur using expressions like x[i] // Changing them to Object( x[i] ) helps the compiler to understand that the // conversion of a seqref to an Object is wanted. template class seqref { protected: SeqBase &s; // the sequence int offset; // item number T the_item; // lvalue public: seqref( SeqBase &seq, sequence_index_type j ) : s( seq ) , offset( j ) , the_item( s.getItem( j ) ) {} seqref( const seqref &range ) : s( range.s ) , offset( range.offset ) , the_item( range.the_item ) {} // TMM: added this seqref ctor for use with STL algorithms seqref( Object &obj ) : s( dynamic_cast< SeqBase&>( obj ) ) , offset( NULL ) , the_item( s.getItem( offset ) ) {} ~seqref() {} operator T() const { // rvalue return the_item; } seqref &operator=( const seqref &rhs ) { //used as lvalue the_item = rhs.the_item; s.setItem( offset, the_item ); return *this; } seqref &operator=( const T &ob ) { // used as lvalue the_item = ob; s.setItem( offset, ob ); return *this; } // forward everything else to the item PyObject *ptr() const { return the_item.ptr(); } int reference_count() const { // the reference count return the_item.reference_count(); } Type type() const { return the_item.type(); } String str() const; String repr() const; bool hasAttr( const std::string &attr_name ) const { return the_item.hasAttr( attr_name ); } Object getAttr( const std::string &attr_name ) const { return the_item.getAttr( attr_name ); } Object getItem( const Object &key ) const { return the_item.getItem( key ); } long hashValue() const { return the_item.hashValue(); } bool isCallable() const { return the_item.isCallable(); } bool isInstance() const { return the_item.isInstance(); } bool isDict() const { return the_item.isDict(); } bool isList() const { return the_item.isList(); } bool isMapping() const { return the_item.isMapping(); } bool isNumeric() const { return the_item.isNumeric(); } bool isSequence() const { return the_item.isSequence(); } bool isTrue() const { return the_item.isTrue(); } bool isType( const Type &t ) const { return the_item.isType( t ); } bool isTuple() const { return the_item.isTuple(); } bool isString() const { return the_item.isString(); } // Commands void setAttr( const std::string &attr_name, const Object &value ) { the_item.setAttr( attr_name, value ); } void delAttr( const std::string &attr_name ) { the_item.delAttr( attr_name ); } void delItem( const Object &key ) { the_item.delItem( key ); } bool operator==( const Object &o2 ) const { return the_item == o2; } bool operator!=( const Object &o2 ) const { return the_item != o2; } bool operator>=( const Object &o2 ) const { return the_item >= o2; } bool operator<=( const Object &o2 ) const { return the_item <= o2; } bool operator<( const Object &o2 ) const { return the_item < o2; } bool operator>( const Object &o2 ) const { return the_item > o2; } }; // end of seqref // class SeqBase // ...the base class for all sequence types template class SeqBase: public Object { public: // STL definitions typedef size_t size_type; typedef seqref reference; typedef T const_reference; typedef seqref *pointer; typedef int difference_type; typedef T value_type; // TMM: 26Jun'01 virtual size_type max_size() const { return std::string::npos; // ? } virtual size_type capacity() const { return size(); } virtual void swap( SeqBase &c ) { SeqBase temp = c; c = ptr(); set( temp.ptr() ); } virtual size_type size() const { return PySequence_Length( ptr() ); } explicit SeqBase() :Object( PyTuple_New( 0 ), true ) { validate(); } explicit SeqBase( PyObject *pyob, bool owned=false ) : Object( pyob, owned ) { validate(); } SeqBase( const Object &ob ) : Object( ob ) { validate(); } // Assignment acquires new ownership of pointer SeqBase &operator=( const Object &rhs ) { return *this = *rhs; } SeqBase &operator=( PyObject *rhsp ) { if( ptr() != rhsp ) set( rhsp ); return *this; } virtual bool accepts( PyObject *pyob ) const { return pyob && PySequence_Check( pyob ); } size_type length() const { return PySequence_Length( ptr() ); } // Element access const T operator[]( sequence_index_type index ) const { return getItem( index ); } seqref operator[]( sequence_index_type index ) { return seqref( *this, index ); } virtual T getItem( sequence_index_type i ) const { return T( asObject( PySequence_GetItem( ptr(), i ) ) ); } virtual void setItem( sequence_index_type i, const T &ob ) { if( PySequence_SetItem( ptr(), i, *ob ) == -1 ) { throw Exception(); } } SeqBase repeat( int count ) const { return SeqBase( PySequence_Repeat( ptr(), count ), true ); } SeqBase concat( const SeqBase &other ) const { return SeqBase( PySequence_Concat( ptr(), *other ), true ); } // more STL compatability const T front() const { return getItem( 0 ); } seqref front() { return seqref( *this, 0 ); } const T back() const { return getItem( size()-1 ); } seqref back() { return seqref( *this, size()-1 ); } void verify_length( size_type required_size ) const { if( size() != required_size ) throw IndexError( "Unexpected SeqBase length." ); } void verify_length( size_type min_size, size_type max_size ) const { size_type n = size(); if( n < min_size || n > max_size ) throw IndexError( "Unexpected SeqBase length." ); } class iterator : public random_access_iterator_parent( seqref ) { protected: friend class SeqBase; SeqBase *seq; int count; public: ~iterator() {} iterator() : seq( 0 ) , count( 0 ) {} iterator( SeqBase *s, int where ) : seq( s ) , count( where ) {} iterator( const iterator &other ) : seq( other.seq ) , count( other.count ) {} bool eql( const iterator &other ) const { return seq->ptr() == other.seq->ptr() && count == other.count; } bool neq( const iterator &other ) const { return seq->ptr() != other.seq->ptr() || count != other.count; } bool lss( const iterator &other ) const { return count < other.count; } bool gtr( const iterator &other ) const { return count > other.count; } bool leq( const iterator &other ) const { return count <= other.count; } bool geq( const iterator &other ) const { return count >= other.count; } seqref operator*() { return seqref( *seq, count ); } seqref operator[]( sequence_index_type i ) { return seqref( *seq, count + i ); } iterator &operator=( const iterator &other ) { if( this != &other ) { seq = other.seq; count = other.count; } return *this; } iterator operator+( int n ) const { return iterator( seq, count + n ); } iterator operator-( int n ) const { return iterator( seq, count - n ); } iterator &operator+=( int n ) { count = count + n; return *this; } iterator &operator-=( int n ) { count = count - n; return *this; } int operator-( const iterator &other ) const { if( seq->ptr() != other.seq->ptr() ) throw RuntimeError( "SeqBase::iterator comparison error" ); return count - other.count; } // prefix ++ iterator &operator++() { count++; return *this; } // postfix ++ iterator operator++( int ) { return iterator( seq, count++ ); } // prefix -- iterator &operator--() { count--; return *this; } // postfix -- iterator operator--( int ) { return iterator( seq, count-- ); } std::string diagnose() const { std::OSTRSTREAM oss; oss << "iterator diagnosis " << seq << ", " << count << std::ends; return std::string( oss.str() ); } }; // end of class SeqBase::iterator iterator begin() { return iterator( this, 0 ); } iterator end() { return iterator( this, length() ); } class const_iterator : public random_access_iterator_parent( const Object ) { protected: friend class SeqBase; const SeqBase *seq; sequence_index_type count; public: ~const_iterator() {} const_iterator() : seq( 0 ) , count( 0 ) {} const_iterator( const SeqBase *s, int where ) : seq( s ) , count( where ) {} const_iterator( const const_iterator &other ) : seq( other.seq ) , count( other.count ) {} const T operator*() const { return seq->getItem( count ); } const T operator[]( sequence_index_type i ) const { return seq->getItem( count + i ); } const_iterator &operator=( const const_iterator &other ) { if( this != &other ) { seq = other.seq; count = other.count; } return *this; } const_iterator operator+( int n ) const { return const_iterator( seq, count + n ); } bool eql( const const_iterator &other ) const { return seq->ptr() == other.seq->ptr() && count == other.count; } bool neq( const const_iterator &other ) const { return seq->ptr() != other.seq->ptr() || count != other.count; } bool lss( const const_iterator &other ) const { return count < other.count; } bool gtr( const const_iterator &other ) const { return count > other.count; } bool leq( const const_iterator &other ) const { return count <= other.count; } bool geq( const const_iterator &other ) const { return count >= other.count; } const_iterator operator-( int n ) { return const_iterator( seq, count - n ); } const_iterator &operator+=( int n ) { count = count + n; return *this; } const_iterator &operator-=( int n ) { count = count - n; return *this; } int operator-( const const_iterator &other ) const { if( *seq != *other.seq ) throw RuntimeError( "SeqBase::const_iterator::- error" ); return count - other.count; } // prefix ++ const_iterator &operator++() { count++; return *this; } // postfix ++ const_iterator operator++( int ) { return const_iterator( seq, count++ ); } // prefix -- const_iterator &operator--() { count--; return *this; } // postfix -- const_iterator operator--( int ) { return const_iterator( seq, count-- ); } }; // end of class SeqBase::const_iterator const_iterator begin() const { return const_iterator( this, 0 ); } const_iterator end() const { return const_iterator( this, length() ); } }; // Here's an important typedef you might miss if reading too fast... typedef SeqBase Sequence; template bool operator==( const EXPLICIT_TYPENAME SeqBase::iterator &left, const EXPLICIT_TYPENAME SeqBase::iterator &right ); template bool operator!=( const EXPLICIT_TYPENAME SeqBase::iterator &left, const EXPLICIT_TYPENAME SeqBase::iterator &right ); template bool operator< ( const EXPLICIT_TYPENAME SeqBase::iterator &left, const EXPLICIT_TYPENAME SeqBase::iterator &right ); template bool operator> ( const EXPLICIT_TYPENAME SeqBase::iterator &left, const EXPLICIT_TYPENAME SeqBase::iterator &right ); template bool operator<=( const EXPLICIT_TYPENAME SeqBase::iterator &left, const EXPLICIT_TYPENAME SeqBase::iterator &right ); template bool operator>=( const EXPLICIT_TYPENAME SeqBase::iterator &left, const EXPLICIT_TYPENAME SeqBase::iterator &right ); template bool operator==( const EXPLICIT_TYPENAME SeqBase::const_iterator &left, const EXPLICIT_TYPENAME SeqBase::const_iterator &right ); template bool operator!=( const EXPLICIT_TYPENAME SeqBase::const_iterator &left, const EXPLICIT_TYPENAME SeqBase::const_iterator &right ); template bool operator< ( const EXPLICIT_TYPENAME SeqBase::const_iterator &left, const EXPLICIT_TYPENAME SeqBase::const_iterator &right ); template bool operator> ( const EXPLICIT_TYPENAME SeqBase::const_iterator &left, const EXPLICIT_TYPENAME SeqBase::const_iterator &right ); template bool operator<=( const EXPLICIT_TYPENAME SeqBase::const_iterator &left, const EXPLICIT_TYPENAME SeqBase::const_iterator &right ); template bool operator>=( const EXPLICIT_TYPENAME SeqBase::const_iterator &left, const EXPLICIT_TYPENAME SeqBase::const_iterator &right ); extern bool operator==( const Sequence::iterator &left, const Sequence::iterator &right ); extern bool operator!=( const Sequence::iterator &left, const Sequence::iterator &right ); extern bool operator< ( const Sequence::iterator &left, const Sequence::iterator &right ); extern bool operator> ( const Sequence::iterator &left, const Sequence::iterator &right ); extern bool operator<=( const Sequence::iterator &left, const Sequence::iterator &right ); extern bool operator>=( const Sequence::iterator &left, const Sequence::iterator &right ); extern bool operator==( const Sequence::const_iterator &left, const Sequence::const_iterator &right ); extern bool operator!=( const Sequence::const_iterator &left, const Sequence::const_iterator &right ); extern bool operator< ( const Sequence::const_iterator &left, const Sequence::const_iterator &right ); extern bool operator> ( const Sequence::const_iterator &left, const Sequence::const_iterator &right ); extern bool operator<=( const Sequence::const_iterator &left, const Sequence::const_iterator &right ); extern bool operator>=( const Sequence::const_iterator &left, const Sequence::const_iterator &right ); // ================================================== // class Char // Python strings return strings as individual elements. // I'll try having a class Char which is a String of length 1 // typedef std::basic_string unicodestring; extern Py_UNICODE unicode_null_string[1]; class Byte: public Object { public: // Membership virtual bool accepts( PyObject *pyob ) const { return pyob != NULL && Py::_Unicode_Check( pyob ) && PySequence_Length( pyob ) == 1; } explicit Byte( PyObject *pyob, bool owned = false ) : Object( pyob, owned ) { validate(); } Byte( const Object &ob ) : Object( ob ) { validate(); } Byte( const std::string &v = "" ) : Object( PyBytes_FromStringAndSize( const_cast( v.c_str() ), 1 ), true ) { validate(); } Byte( char v ) : Object( PyBytes_FromStringAndSize( &v, 1 ), true ) { validate(); } // Assignment acquires new ownership of pointer Byte &operator=( const Object &rhs ) { return *this = *rhs; } Byte &operator=( PyObject *rhsp ) { if( ptr() != rhsp ) set( rhsp ); return *this; } // Assignment from C string Byte &operator=( const std::string &v ) { set( PyBytes_FromStringAndSize( const_cast( v.c_str() ),1 ), true ); return *this; } Byte &operator=( char v ) { set( PyUnicode_FromStringAndSize( &v, 1 ), true ); return *this; } // Conversion operator Bytes() const; }; class Bytes: public SeqBase { public: // Membership virtual bool accepts( PyObject *pyob ) const { return pyob != NULL && Py::_Bytes_Check( pyob ); } virtual size_type capacity() const { return max_size(); } explicit Bytes( PyObject *pyob, bool owned = false ) : SeqBase( pyob, owned ) { validate(); } Bytes( const Object &ob ) : SeqBase( ob ) { validate(); } Bytes() : SeqBase( PyBytes_FromStringAndSize( "", 0 ), true ) { validate(); } Bytes( const std::string &v ) : SeqBase( PyBytes_FromStringAndSize( const_cast( v.data() ), static_cast( v.length() ) ), true ) { validate(); } Bytes( const std::string &v, Py_ssize_t vsize ) : SeqBase( PyBytes_FromStringAndSize( const_cast( v.data() ), static_cast( vsize ) ), true ) { validate(); } Bytes( const char *v ) : SeqBase( PyBytes_FromString( v ), true ) { validate(); } Bytes( const char *v, Py_ssize_t vsize ) : SeqBase( PyBytes_FromStringAndSize( const_cast( v ), vsize ), true ) { validate(); } // Assignment acquires new ownership of pointer Bytes &operator=( const Object &rhs ) { return *this = *rhs; } Bytes &operator=( PyObject *rhsp ) { if( ptr() != rhsp ) set( rhsp ); return *this; } // Assignment from C string Bytes &operator=( const std::string &v ) { set( PyBytes_FromStringAndSize( const_cast( v.data() ), static_cast( v.length() ) ), true ); return *this; } String decode( const char *encoding, const char *error="strict" ); // Queries virtual size_type size() const { return static_cast( PyBytes_Size( ptr() ) ); } operator std::string() const { return as_std_string(); } std::string as_std_string() const { return std::string( PyBytes_AsString( ptr() ), static_cast( PyBytes_Size( ptr() ) ) ); } }; class Char: public Object { public: // Membership virtual bool accepts( PyObject *pyob ) const { return pyob != 0 &&( Py::_Unicode_Check( pyob ) ) && PySequence_Length( pyob ) == 1; } explicit Char( PyObject *pyob, bool owned = false ) : Object( pyob, owned ) { validate(); } Char( const Object &ob ) : Object( ob ) { validate(); } Char( int v ) : Object( PyUnicode_FromOrdinal( v ), true ) { validate(); } Char( Py_UNICODE v ) : Object( PyUnicode_FromOrdinal( v ), true ) { validate(); } Char( const unicodestring &v ) : Object( PyUnicode_FromUnicode( const_cast( v.data() ),1 ), true ) { validate(); } // Assignment acquires new ownership of pointer Char &operator=( const Object &rhs ) { return *this = *rhs; } Char &operator=( PyObject *rhsp ) { if( ptr() != rhsp ) set( rhsp ); return *this; } Char &operator=( const unicodestring &v ) { set( PyUnicode_FromUnicode( const_cast( v.data() ), 1 ), true ); return *this; } Char &operator=( int v_ ) { Py_UNICODE v( v_ ); set( PyUnicode_FromUnicode( &v, 1 ), true ); return *this; } Char &operator=( Py_UNICODE v ) { set( PyUnicode_FromUnicode( &v, 1 ), true ); return *this; } // Conversion operator String() const; }; class String: public SeqBase { public: virtual size_type capacity() const { return max_size(); } // Membership virtual bool accepts( PyObject *pyob ) const { return pyob != NULL && Py::_Unicode_Check( pyob ); } explicit String( PyObject *pyob, bool owned = false ) : SeqBase( pyob, owned ) { validate(); } String( const Object &ob ) : SeqBase( ob ) { validate(); } String() : SeqBase( PyUnicode_FromString( "" ) ) { validate(); } String( const char *latin1 ) : SeqBase( PyUnicode_FromString( latin1 ) ) { validate(); } String( const std::string &latin1 ) : SeqBase( PyUnicode_FromStringAndSize( latin1.c_str(), latin1.size() ) ) { validate(); } String( const char *latin1, Py_ssize_t size ) : SeqBase( PyUnicode_FromStringAndSize( latin1, size ) ) { validate(); } /* [Taken from Pythons's unicode.h] Many of these APIs take two arguments encoding and errors. These parameters encoding and errors have the same semantics as the ones of the builtin unicode() API. Setting encoding to NULL causes the default encoding to be used. Error handling is set by errors which may also be set to NULL meaning to use the default handling defined for the codec. Default error handling for all builtin codecs is "strict" (ValueErrors are raised). The codecs all use a similar interface. Only deviation from the generic ones are documented. */ String( const std::string &s, const char *encoding, const char *errors=NULL ) : SeqBase( PyUnicode_Decode( s.c_str(), s.size(), encoding, errors ), true ) { validate(); } String( const char *s, const char *encoding, const char *errors=NULL ) : SeqBase( PyUnicode_Decode( s, strlen(s), encoding, errors ), true ) { validate(); } String( const char *s, Py_ssize_t size, const char *encoding, const char *errors=NULL ) : SeqBase( PyUnicode_Decode( s, size, encoding, errors ), true ) { validate(); } String( const Py_UNICODE *s, int length ) : SeqBase( PyUnicode_FromUnicode( s, length ), true ) { validate(); } // Assignment acquires new ownership of pointer String &operator=( const Object &rhs ) { return *this = *rhs; } String &operator=( PyObject *rhsp ) { if( ptr() != rhsp ) set( rhsp ); return *this; } String &operator=( const unicodestring &v ) { set( PyUnicode_FromUnicode( const_cast( v.data() ), static_cast( v.length() ) ), true ); return *this; } // Encode Bytes encode( const char *encoding, const char *error="strict" ) const { return Bytes( PyUnicode_AsEncodedString( ptr(), encoding, error ), true ); } // Queries virtual size_type size() const { return static_cast( PyUnicode_GET_SIZE( ptr() ) ); } unicodestring as_unicodestring() const { return unicodestring( PyUnicode_AS_UNICODE( ptr() ), static_cast( PyUnicode_GET_SIZE( ptr() ) ) ); } operator std::string() const { // use the default encoding return as_std_string( NULL ); } std::string as_std_string( const char *encoding=NULL, const char *error="strict" ) const { Bytes b( encode( encoding, error ) ); return b.as_std_string(); } const Py_UNICODE *unicode_data() const { return PyUnicode_AS_UNICODE( ptr() ); } }; // ================================================== // class Tuple class Tuple: public Sequence { public: virtual void setItem( sequence_index_type offset, const Object&ob ) { // note PyTuple_SetItem is a thief... if( PyTuple_SetItem( ptr(), offset, new_reference_to( ob ) ) == -1 ) { throw Exception(); } } // Constructor explicit Tuple( PyObject *pyob, bool owned = false ) : Sequence( pyob, owned ) { validate(); } Tuple( const Object &ob ) : Sequence( ob ) { validate(); } // New tuple of a given size explicit Tuple( int size = 0 ) { set( PyTuple_New( size ), true ); validate(); for( sequence_index_type i=0; i < size; i++ ) { if( PyTuple_SetItem( ptr(), i, new_reference_to( Py::_None() ) ) == -1 ) { throw Exception(); } } } // Tuple from any sequence explicit Tuple( const Sequence &s ) { sequence_index_type limit( sequence_index_type( s.length() ) ); set( PyTuple_New( limit ), true ); validate(); for( sequence_index_type i=0; i < limit; i++ ) { if( PyTuple_SetItem( ptr(), i, new_reference_to( s[i] ) ) == -1 ) { throw Exception(); } } } // Assignment acquires new ownership of pointer Tuple &operator=( const Object &rhs ) { return *this = *rhs; } Tuple &operator=( PyObject *rhsp ) { if( ptr() != rhsp ) set( rhsp ); return *this; } // Membership virtual bool accepts( PyObject *pyob ) const { return pyob && Py::_Tuple_Check( pyob ); } Tuple getSlice( int i, int j ) const { return Tuple( PySequence_GetSlice( ptr(), i, j ), true ); } }; class TupleN: public Tuple { public: TupleN() : Tuple( 0 ) { } TupleN( const Object &obj1 ) : Tuple( 1 ) { setItem( 0, obj1 ); } TupleN( const Object &obj1, const Object &obj2 ) : Tuple( 2 ) { setItem( 0, obj1 ); setItem( 1, obj2 ); } TupleN( const Object &obj1, const Object &obj2, const Object &obj3 ) : Tuple( 3 ) { setItem( 0, obj1 ); setItem( 1, obj2 ); setItem( 2, obj3 ); } TupleN( const Object &obj1, const Object &obj2, const Object &obj3, const Object &obj4 ) : Tuple( 4 ) { setItem( 0, obj1 ); setItem( 1, obj2 ); setItem( 2, obj3 ); setItem( 3, obj4 ); } TupleN( const Object &obj1, const Object &obj2, const Object &obj3, const Object &obj4, const Object &obj5 ) : Tuple( 5 ) { setItem( 0, obj1 ); setItem( 1, obj2 ); setItem( 2, obj3 ); setItem( 3, obj4 ); setItem( 4, obj5 ); } TupleN( const Object &obj1, const Object &obj2, const Object &obj3, const Object &obj4, const Object &obj5, const Object &obj6 ) : Tuple( 6 ) { setItem( 0, obj1 ); setItem( 1, obj2 ); setItem( 2, obj3 ); setItem( 3, obj4 ); setItem( 4, obj5 ); setItem( 5, obj6 ); } TupleN( const Object &obj1, const Object &obj2, const Object &obj3, const Object &obj4, const Object &obj5, const Object &obj6, const Object &obj7 ) : Tuple( 7 ) { setItem( 0, obj1 ); setItem( 1, obj2 ); setItem( 2, obj3 ); setItem( 3, obj4 ); setItem( 4, obj5 ); setItem( 5, obj6 ); setItem( 6, obj7 ); } TupleN( const Object &obj1, const Object &obj2, const Object &obj3, const Object &obj4, const Object &obj5, const Object &obj6, const Object &obj7, const Object &obj8 ) : Tuple( 8 ) { setItem( 0, obj1 ); setItem( 1, obj2 ); setItem( 2, obj3 ); setItem( 3, obj4 ); setItem( 4, obj5 ); setItem( 5, obj6 ); setItem( 6, obj7 ); setItem( 7, obj8 ); } TupleN( const Object &obj1, const Object &obj2, const Object &obj3, const Object &obj4, const Object &obj5, const Object &obj6, const Object &obj7, const Object &obj8, const Object &obj9 ) : Tuple( 9 ) { setItem( 0, obj1 ); setItem( 1, obj2 ); setItem( 2, obj3 ); setItem( 3, obj4 ); setItem( 4, obj5 ); setItem( 5, obj6 ); setItem( 6, obj7 ); setItem( 7, obj8 ); setItem( 8, obj9 ); } virtual ~TupleN() { } }; // ================================================== // class List class List: public Sequence { public: // Constructor explicit List( PyObject *pyob, bool owned = false ) : Sequence( pyob, owned ) { validate(); } List( const Object &ob ) : Sequence( ob ) { validate(); } // Creation at a fixed size List( int size = 0 ) { set( PyList_New( size ), true ); validate(); for( sequence_index_type i=0; i < size; i++ ) { if( PyList_SetItem( ptr(), i, new_reference_to( Py::_None() ) ) == -1 ) { throw Exception(); } } } // List from a sequence List( const Sequence &s ) : Sequence() { int n =( int )s.length(); set( PyList_New( n ), true ); validate(); for( sequence_index_type i=0; i < n; i++ ) { if( PyList_SetItem( ptr(), i, new_reference_to( s[i] ) ) == -1 ) { throw Exception(); } } } virtual size_type capacity() const { return max_size(); } // Assignment acquires new ownership of pointer List &operator=( const Object &rhs ) { return *this = *rhs; } List &operator=( PyObject *rhsp ) { if( ptr() != rhsp ) set( rhsp ); return *this; } // Membership virtual bool accepts( PyObject *pyob ) const { return pyob && Py::_List_Check( pyob ); } List getSlice( int i, int j ) const { return List( PyList_GetSlice( ptr(), i, j ), true ); } void setSlice( int i, int j, const Object &v ) { if( PyList_SetSlice( ptr(), i, j, *v ) == -1 ) { throw Exception(); } } void append( const Object &ob ) { if( PyList_Append( ptr(), *ob ) == -1 ) { throw Exception(); } } void extend( const Object &ob ) { setSlice( size(), size(), ob ); } void insert( int i, const Object &ob ) { if( PyList_Insert( ptr(), i, *ob ) == -1 ) { throw Exception(); } } void sort() { if( PyList_Sort( ptr() ) == -1 ) { throw Exception(); } } void reverse() { if( PyList_Reverse( ptr() ) == -1 ) { throw Exception(); } } }; // Mappings // ================================================== template class mapref { protected: MapBase &s; // the map Object key; // item key T the_item; public: mapref( MapBase &map, const std::string &k ) : s( map ), the_item() { key = String( k ); if( map.hasKey( key ) ) the_item = map.getItem( key ); } mapref( MapBase &map, const Object &k ) : s( map ), key( k ), the_item() { if( map.hasKey( key ) ) the_item = map.getItem( key ); } virtual ~mapref() {} // MapBase stuff // lvalue mapref &operator=( const mapref &other ) { if( this != &other ) { the_item = other.the_item; s.setItem( key, other.the_item ); } return *this; } mapref &operator=( const T &ob ) { the_item = ob; s.setItem( key, ob ); return *this; } // rvalue operator T() const { return the_item; } // forward everything else to the_item PyObject *ptr() const { return the_item.ptr(); } int reference_count() const { // the mapref count return the_item.reference_count(); } Type type() const { return the_item.type(); } String str() const { return the_item.str(); } String repr() const { return the_item.repr(); } bool hasAttr( const std::string &attr_name ) const { return the_item.hasAttr( attr_name ); } Object getAttr( const std::string &attr_name ) const { return the_item.getAttr( attr_name ); } Object getItem( const Object &k ) const { return the_item.getItem( k ); } long hashValue() const { return the_item.hashValue(); } bool isCallable() const { return the_item.isCallable(); } bool isInstance() const { return the_item.isInstance(); } bool isList() const { return the_item.isList(); } bool isMapping() const { return the_item.isMapping(); } bool isNumeric() const { return the_item.isNumeric(); } bool isSequence() const { return the_item.isSequence(); } bool isTrue() const { return the_item.isTrue(); } bool isType( const Type &t ) const { return the_item.isType( t ); } bool isTuple() const { return the_item.isTuple(); } bool isString() const { return the_item.isString(); } // Commands void setAttr( const std::string &attr_name, const Object &value ) { the_item.setAttr( attr_name, value ); } void delAttr( const std::string &attr_name ) { the_item.delAttr( attr_name ); } void delItem( const Object &k ) { the_item.delItem( k ); } }; // end of mapref #if 0 // TMM: now for mapref template< class T > bool operator==( const mapref &left, const mapref &right ) { return true; // NOT completed. } template< class T > bool operator!=( const mapref &left, const mapref &right ) { return true; // not completed. } #endif template class MapBase: public Object { protected: explicit MapBase() {} public: // reference: proxy class for implementing [] // TMM: 26Jun'01 - the types // If you assume that Python mapping is a hash_map... // hash_map::value_type is not assignable, but //( *it ).second = data must be a valid expression typedef size_t size_type; typedef Object key_type; typedef mapref data_type; typedef std::pair< const T, T > value_type; typedef std::pair< const T, mapref > reference; typedef const std::pair< const T, const T > const_reference; typedef std::pair< const T, mapref > pointer; // Constructor explicit MapBase( PyObject *pyob, bool owned = false ) : Object( pyob, owned ) { validate(); } // TMM: 02Jul'01 - changed MapBase to Object in next line MapBase( const Object &ob ) : Object( ob ) { validate(); } // Assignment acquires new ownership of pointer MapBase &operator=( const Object &rhs ) { return *this = *rhs; } MapBase &operator=( PyObject *rhsp ) { if( ptr() != rhsp ) set( rhsp ); return *this; } // Membership virtual bool accepts( PyObject *pyob ) const { return pyob && PyMapping_Check( pyob ); } // Clear -- PyMapping Clear is missing // void clear() { List k = keys(); for( List::iterator i = k.begin(); i != k.end(); i++ ) { delItem( *i ); } } virtual size_type size() const { return PyMapping_Length( ptr() ); } // Element Access T operator[]( const std::string &key ) const { return getItem( key ); } T operator[]( const Object &key ) const { return getItem( key ); } mapref operator[]( const char *key ) { return mapref( *this, key ); } mapref operator[]( const std::string &key ) { return mapref( *this, key ); } mapref operator[]( const Object &key ) { return mapref( *this, key ); } int length() const { return PyMapping_Length( ptr() ); } bool hasKey( const std::string &s ) const { return PyMapping_HasKeyString( ptr(),const_cast( s.c_str() ) ) != 0; } bool hasKey( const Object &s ) const { return PyMapping_HasKey( ptr(), s.ptr() ) != 0; } T getItem( const std::string &s ) const { return T( asObject( PyMapping_GetItemString( ptr(),const_cast( s.c_str() ) ) ) ); } T getItem( const Object &s ) const { return T( asObject( PyObject_GetItem( ptr(), s.ptr() ) ) ); } virtual void setItem( const char *s, const Object &ob ) { if( PyMapping_SetItemString( ptr(), const_cast( s ), *ob ) == -1 ) { throw Exception(); } } virtual void setItem( const std::string &s, const Object &ob ) { if( PyMapping_SetItemString( ptr(), const_cast( s.c_str() ), *ob ) == -1 ) { throw Exception(); } } virtual void setItem( const Object &s, const Object &ob ) { if( PyObject_SetItem( ptr(), s.ptr(), ob.ptr() ) == -1 ) { throw Exception(); } } void delItem( const std::string &s ) { if( PyMapping_DelItemString( ptr(), const_cast( s.c_str() ) ) == -1 ) { throw Exception(); } } void delItem( const Object &s ) { if( PyMapping_DelItem( ptr(), *s ) == -1 ) { throw Exception(); } } // Queries List keys() const { return List( PyMapping_Keys( ptr() ), true ); } List values() const { // each returned item is a (key, value) pair return List( PyMapping_Values( ptr() ), true ); } List items() const { return List( PyMapping_Items( ptr() ), true ); } class iterator { // : public forward_iterator_parent( std::pair ) { protected: typedef std::forward_iterator_tag iterator_category; typedef std::pair< const T, T > value_type; typedef int difference_type; typedef std::pair< const T, mapref > pointer; typedef std::pair< const T, mapref > reference; friend class MapBase; // MapBase *map; List keys; // for iterating over the map int pos; // index into the keys public: ~iterator() {} iterator() : map( 0 ) , keys() , pos( 0 ) {} iterator( MapBase *m, bool end = false ) : map( m ) , keys( m->keys() ) , pos( end ? keys.length() : 0 ) {} iterator( const iterator &other ) : map( other.map ) , keys( other.keys ) , pos( other.pos ) {} iterator( MapBase *map_, List keys_, int pos_ ) : map( map_ ) , keys( keys_ ) , pos( pos_ ) {} reference operator*() { Object key = keys[ pos ]; return std::make_pair( key, mapref( *map, key ) ); } iterator &operator=( const iterator &other ) { if( this != &other ) { map = other.map; keys = other.keys; pos = other.pos; } return *this; } bool eql( const iterator &other ) const { return map->ptr() == other.map->ptr() && pos == other.pos; } bool neq( const iterator &other ) const { return map->ptr() != other.map->ptr() || pos != other.pos; } // pointer operator->() { // return ; // } // prefix ++ iterator &operator++() { pos++; return *this; } // postfix ++ iterator operator++( int ) { return iterator( map, keys, pos++ ); } // prefix -- iterator &operator--() { pos--; return *this; } // postfix -- iterator operator--( int ) { return iterator( map, keys, pos-- ); } std::string diagnose() const { std::OSTRSTREAM oss; oss << "iterator diagnosis " << map << ", " << pos << std::ends; return std::string( oss.str() ); } }; // end of class MapBase::iterator iterator begin() { return iterator( this, false ); } iterator end() { return iterator( this, true ); } class const_iterator { protected: typedef std::forward_iterator_tag iterator_category; typedef const std::pair< const T, T > value_type; typedef int difference_type; typedef const std::pair< const T, T > pointer; typedef const std::pair< const T, T > reference; friend class MapBase; const MapBase *map; List keys; // for iterating over the map int pos; // index into the keys public: ~const_iterator() {} const_iterator() : map( 0 ) , keys() , pos() {} const_iterator( const MapBase *m, List k, int p ) : map( m ) , keys( k ) , pos( p ) {} const_iterator( const const_iterator &other ) : map( other.map ) , keys( other.keys ) , pos( other.pos ) {} bool eql( const const_iterator &other ) const { return map->ptr() == other.map->ptr() && pos == other.pos; } bool neq( const const_iterator &other ) const { return map->ptr() != other.map->ptr() || pos != other.pos; } // const_reference operator*() { // Object key = *pos; // return std::make_pair( key, map->[key] ); // GCC < 3 barfes on this line at the '['. // } const_reference operator*() { Object key = keys[ pos ]; return std::make_pair( key, mapref( *map, key ) ); } const_iterator &operator=( const const_iterator &other ) { if( this != &other ) { map = other.map; keys = other.keys; pos = other.pos; } return *this; } // prefix ++ const_iterator &operator++() { pos++; return *this; } // postfix ++ const_iterator operator++( int ) { return const_iterator( map, keys, pos++ ); } // prefix -- const_iterator &operator--() { pos--; return *this; } // postfix -- const_iterator operator--( int ) { return const_iterator( map, keys, pos-- ); } }; // end of class MapBase::const_iterator const_iterator begin() const { return const_iterator( this, keys(), 0 ); } const_iterator end() const { return const_iterator( this, keys(), length() ); } }; // end of MapBase typedef MapBase Mapping; template bool operator==( const EXPLICIT_TYPENAME MapBase::iterator &left, const EXPLICIT_TYPENAME MapBase::iterator &right ); template bool operator!=( const EXPLICIT_TYPENAME MapBase::iterator &left, const EXPLICIT_TYPENAME MapBase::iterator &right ); template bool operator==( const EXPLICIT_TYPENAME MapBase::const_iterator &left, const EXPLICIT_TYPENAME MapBase::const_iterator &right ); template bool operator!=( const EXPLICIT_TYPENAME MapBase::const_iterator &left, const EXPLICIT_TYPENAME MapBase::const_iterator &right ); extern bool operator==( const Mapping::iterator &left, const Mapping::iterator &right ); extern bool operator!=( const Mapping::iterator &left, const Mapping::iterator &right ); extern bool operator==( const Mapping::const_iterator &left, const Mapping::const_iterator &right ); extern bool operator!=( const Mapping::const_iterator &left, const Mapping::const_iterator &right ); // ================================================== // class Dict class Dict: public Mapping { public: // Constructor explicit Dict( PyObject *pyob, bool owned=false ) : Mapping( pyob, owned ) { validate(); } Dict( const Object &ob ) : Mapping( ob ) { validate(); } // Creation Dict() { set( PyDict_New(), true ); validate(); } // Assignment acquires new ownership of pointer Dict &operator=( const Object &rhs ) { return *this = *rhs; } Dict &operator=( PyObject *rhsp ) { if( ptr() != rhsp ) set( rhsp ); return *this; } // Membership virtual bool accepts( PyObject *pyob ) const { return pyob && Py::_Dict_Check( pyob ); } }; class Callable: public Object { public: // Constructor explicit Callable() : Object() {} explicit Callable( PyObject *pyob, bool owned = false ) : Object( pyob, owned ) { validate(); } Callable( const Object &ob ) : Object( ob ) { validate(); } // Assignment acquires new ownership of pointer Callable &operator=( const Object &rhs ) { return *this = *rhs; } Callable &operator=( PyObject *rhsp ) { if( ptr() != rhsp ) set( rhsp ); return *this; } // Membership virtual bool accepts( PyObject *pyob ) const { return pyob && PyCallable_Check( pyob ); } // Call Object apply( const Tuple &args ) const { return asObject( PyObject_CallObject( ptr(), args.ptr() ) ); } // Call with keywords Object apply( const Tuple &args, const Dict &kw ) const { return asObject( PyEval_CallObjectWithKeywords( ptr(), args.ptr(), kw.ptr() ) ); } Object apply( PyObject *pargs = 0 ) const { return apply( Tuple( pargs ) ); } }; class Module: public Object { public: explicit Module( PyObject *pyob, bool owned = false ) : Object( pyob, owned ) { validate(); } // Construct from module name explicit Module( const std::string &s ) : Object() { PyObject *m = PyImport_AddModule( const_cast( s.c_str() ) ); set( m, false ); validate(); } // Copy constructor acquires new ownership of pointer Module( const Module &ob ) : Object( *ob ) { validate(); } Module &operator=( const Object &rhs ) { return *this = *rhs; } Module &operator=( PyObject *rhsp ) { if( ptr() != rhsp ) set( rhsp ); return *this; } Dict getDict() const { return Dict( PyModule_GetDict( ptr() ) ); // Caution -- PyModule_GetDict returns borrowed reference! } }; // Call function helper inline Object Object::callMemberFunction( const std::string &function_name ) const { Callable target( getAttr( function_name ) ); Tuple args( 0 ); return target.apply( args ); } inline Object Object::callMemberFunction( const std::string &function_name, const Tuple &args ) const { Callable target( getAttr( function_name ) ); return target.apply( args ); } inline Object Object::callMemberFunction( const std::string &function_name, const Tuple &args, const Dict &kw ) const { Callable target( getAttr( function_name ) ); return target.apply( args, kw ); } // Numeric interface inline Object operator+( const Object &a ) { return asObject( PyNumber_Positive( *a ) ); } inline Object operator-( const Object &a ) { return asObject( PyNumber_Negative( *a ) ); } inline Object abs( const Object &a ) { return asObject( PyNumber_Absolute( *a ) ); } //------------------------------------------------------------ // operator + inline Object operator+( const Object &a, const Object &b ) { return asObject( PyNumber_Add( *a, *b ) ); } inline Object operator+( const Object &a, int j ) { return asObject( PyNumber_Add( *a, *Long( j ) ) ); } inline Object operator+( const Object &a, long j ) { return asObject( PyNumber_Add( *a, *Long( j ) ) ); } inline Object operator+( const Object &a, double v ) { return asObject( PyNumber_Add( *a, *Float( v ) ) ); } inline Object operator+( int j, const Object &b ) { return asObject( PyNumber_Add( *Long( j ), *b ) ); } inline Object operator+( long j, const Object &b ) { return asObject( PyNumber_Add( *Long( j ), *b ) ); } inline Object operator+( double v, const Object &b ) { return asObject( PyNumber_Add( *Float( v ), *b ) ); } //------------------------------------------------------------ // operator - inline Object operator-( const Object &a, const Object &b ) { return asObject( PyNumber_Subtract( *a, *b ) ); } inline Object operator-( const Object &a, int j ) { return asObject( PyNumber_Subtract( *a, *Long( j ) ) ); } inline Object operator-( const Object &a, double v ) { return asObject( PyNumber_Subtract( *a, *Float( v ) ) ); } inline Object operator-( int j, const Object &b ) { return asObject( PyNumber_Subtract( *Long( j ), *b ) ); } inline Object operator-( double v, const Object &b ) { return asObject( PyNumber_Subtract( *Float( v ), *b ) ); } //------------------------------------------------------------ // operator * inline Object operator*( const Object &a, const Object &b ) { return asObject( PyNumber_Multiply( *a, *b ) ); } inline Object operator*( const Object &a, int j ) { return asObject( PyNumber_Multiply( *a, *Long( j ) ) ); } inline Object operator*( const Object &a, double v ) { return asObject( PyNumber_Multiply( *a, *Float( v ) ) ); } inline Object operator*( int j, const Object &b ) { return asObject( PyNumber_Multiply( *Long( j ), *b ) ); } inline Object operator*( double v, const Object &b ) { return asObject( PyNumber_Multiply( *Float( v ), *b ) ); } //------------------------------------------------------------ // operator / inline Object operator/( const Object &a, const Object &b ) { return asObject( PyNumber_TrueDivide( *a, *b ) ); } inline Object operator/( const Object &a, int j ) { return asObject( PyNumber_TrueDivide( *a, *Long( j ) ) ); } inline Object operator/( const Object &a, double v ) { return asObject( PyNumber_TrueDivide( *a, *Float( v ) ) ); } inline Object operator/( int j, const Object &b ) { return asObject( PyNumber_TrueDivide( *Long( j ), *b ) ); } inline Object operator/( double v, const Object &b ) { return asObject( PyNumber_TrueDivide( *Float( v ), *b ) ); } //------------------------------------------------------------ // operator % inline Object operator%( const Object &a, const Object &b ) { return asObject( PyNumber_Remainder( *a, *b ) ); } inline Object operator%( const Object &a, int j ) { return asObject( PyNumber_Remainder( *a, *Long( j ) ) ); } inline Object operator%( const Object &a, double v ) { return asObject( PyNumber_Remainder( *a, *Float( v ) ) ); } inline Object operator%( int j, const Object &b ) { return asObject( PyNumber_Remainder( *Long( j ), *b ) ); } inline Object operator%( double v, const Object &b ) { return asObject( PyNumber_Remainder( *Float( v ), *b ) ); } //------------------------------------------------------------ // type inline Object type( const Exception &) // return the type of the error { PyObject *ptype, *pvalue, *ptrace; PyErr_Fetch( &ptype, &pvalue, &ptrace ); Object result; if( ptype ) result = ptype; PyErr_Restore( ptype, pvalue, ptrace ); return result; } inline Object value( const Exception &) // return the value of the error { PyObject *ptype, *pvalue, *ptrace; PyErr_Fetch( &ptype, &pvalue, &ptrace ); Object result; if( pvalue ) result = pvalue; PyErr_Restore( ptype, pvalue, ptrace ); return result; } inline Object trace( const Exception &) // return the traceback of the error { PyObject *ptype, *pvalue, *ptrace; PyErr_Fetch( &ptype, &pvalue, &ptrace ); Object result; if( ptrace ) result = ptrace; PyErr_Restore( ptype, pvalue, ptrace ); return result; } template String seqref::str() const { return the_item.str(); } template String seqref::repr() const { return the_item.repr(); } } // namespace Py #endif // __CXX_Objects__h pycxx-6.2.5/CXX/Python3/PythonType.hxx000644 000771 000000 00000010766 11146615306 020050 0ustar00barrywheel000000 000000 //----------------------------------------------------------------------------- // // Copyright (c) 1998 - 2007, The Regents of the University of California // Produced at the Lawrence Livermore National Laboratory // All rights reserved. // // This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The // full copyright notice is contained in the file COPYRIGHT located at the root // of the PyCXX distribution. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // - Redistributions of source code must retain the above copyright notice, // this list of conditions and the disclaimer below. // - Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the disclaimer (as noted below) in the // documentation and/or materials provided with the distribution. // - Neither the name of the UC/LLNL nor the names of its contributors may be // used to endorse or promote products derived from this software without // specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF // CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH // DAMAGE. // //----------------------------------------------------------------------------- #ifndef __CXX_PythonType__h #define __CXX_PythonType__h namespace Py { class PythonType { public: // if you define one sequence method you must define // all of them except the assigns PythonType( size_t base_size, int itemsize, const char *default_name ); virtual ~PythonType(); const char *getName() const; const char *getDoc() const; PyTypeObject *type_object() const; PythonType &name( const char *nam ); PythonType &doc( const char *d ); PythonType &supportClass( void ); #ifdef PYCXX_PYTHON_2TO3 PythonType &supportPrint( void ); #endif PythonType &supportGetattr( void ); PythonType &supportSetattr( void ); PythonType &supportGetattro( void ); PythonType &supportSetattro( void ); #ifdef PYCXX_PYTHON_2TO3 PythonType &supportCompare( void ); #endif PythonType &supportRichCompare( void ); PythonType &supportRepr( void ); PythonType &supportStr( void ); PythonType &supportHash( void ); PythonType &supportCall( void ); PythonType &supportIter( void ); PythonType &supportSequenceType( void ); PythonType &supportMappingType( void ); PythonType &supportNumberType( void ); PythonType &supportBufferType( void ); PythonType &set_tp_dealloc( void (*tp_dealloc)( PyObject * ) ); PythonType &set_tp_init( int (*tp_init)( PyObject *self, PyObject *args, PyObject *kwds ) ); PythonType &set_tp_new( PyObject *(*tp_new)( PyTypeObject *subtype, PyObject *args, PyObject *kwds ) ); PythonType &set_methods( PyMethodDef *methods ); // call once all support functions have been called to ready the type bool readyType(); protected: void init_sequence(); void init_mapping(); void init_number(); void init_buffer(); PyTypeObject *table; PySequenceMethods *sequence_table; PyMappingMethods *mapping_table; PyNumberMethods *number_table; PyBufferProcs *buffer_table; private: // // prevent the compiler generating these unwanted functions // PythonType( const PythonType &tb ); // unimplemented void operator=( const PythonType &t ); // unimplemented }; } // Namespace Py // End of __CXX_PythonType__h #endif pycxx-6.2.5/CXX/Python2/Config.hxx000644 000771 000000 00000010022 11230627123 017104 0ustar00barrywheel000000 000000 //----------------------------------------------------------------------------- // // Copyright (c) 1998 - 2007, The Regents of the University of California // Produced at the Lawrence Livermore National Laboratory // All rights reserved. // // This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The // full copyright notice is contained in the file COPYRIGHT located at the root // of the PyCXX distribution. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // - Redistributions of source code must retain the above copyright notice, // this list of conditions and the disclaimer below. // - Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the disclaimer (as noted below) in the // documentation and/or materials provided with the distribution. // - Neither the name of the UC/LLNL nor the names of its contributors may be // used to endorse or promote products derived from this software without // specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF // CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH // DAMAGE. // //----------------------------------------------------------------------------- #ifndef __PyCXX_config_hh__ #define __PyCXX_config_hh__ // // Microsoft VC++ 6.0 has no traits // #if defined( _MSC_VER ) # define STANDARD_LIBRARY_HAS_ITERATOR_TRAITS 1 #elif defined( __GNUC__ ) # if __GNUC__ >= 3 # define STANDARD_LIBRARY_HAS_ITERATOR_TRAITS 1 # else # define STANDARD_LIBRARY_HAS_ITERATOR_TRAITS 0 #endif // // Assume all other compilers do // #else // Macros to deal with deficiencies in compilers # define STANDARD_LIBRARY_HAS_ITERATOR_TRAITS 1 #endif #if STANDARD_LIBRARY_HAS_ITERATOR_TRAITS # define random_access_iterator_parent(itemtype) std::iterator #else # define random_access_iterator_parent(itemtype) std::random_access_iterator #endif // // Which C++ standard is in use? // #if defined( _MSC_VER ) # if _MSC_VER <= 1200 // MSVC++ 6.0 # define PYCXX_ISO_CPP_LIB 0 # define STR_STREAM # define TEMPLATE_TYPENAME class # else # define PYCXX_ISO_CPP_LIB 1 # define STR_STREAM # define TEMPLATE_TYPENAME typename # endif #elif defined( __GNUC__ ) # if __GNUC__ >= 3 # define PYCXX_ISO_CPP_LIB 1 # define STR_STREAM # define TEMPLATE_TYPENAME typename # else # define PYCXX_ISO_CPP_LIB 0 # define STR_STREAM # define TEMPLATE_TYPENAME class # endif #endif #if PYCXX_ISO_CPP_LIB # define STR_STREAM # define OSTRSTREAM ostringstream # define EXPLICIT_TYPENAME typename # define EXPLICIT_CLASS class # define TEMPLATE_TYPENAME typename #else # define STR_STREAM # define OSTRSTREAM ostrstream # define EXPLICIT_TYPENAME # define EXPLICIT_CLASS # define TEMPLATE_TYPENAME class #endif // before 2.5 Py_ssize_t was missing #ifndef PY_MAJOR_VERSION #error not defined PY_MAJOR_VERSION #endif #if PY_MAJOR_VERSION < 2 || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION < 5) typedef int Py_ssize_t; #endif #endif // __PyCXX_config_hh__ pycxx-6.2.5/CXX/Python2/CxxDebug.hxx000644 000771 000000 00000000402 11150315604 017410 0ustar00barrywheel000000 000000 // // CxxDebug.hxx // // Copyright (c) 2008 Barry A. Scott // #ifndef __CXX_Debug_hxx #define __CXX_Debug_hxx // // Functions useful when debugging PyCXX // #ifdef PYCXX_DEBUG extern void bpt(); extern void printRefCount( PyObject *obj ); #endif #endif pycxx-6.2.5/CXX/Python2/Exception.hxx000644 000771 000000 00000016152 11400430272 017643 0ustar00barrywheel000000 000000 //----------------------------------------------------------------------------- // // Copyright (c) 1998 - 2007, The Regents of the University of California // Produced at the Lawrence Livermore National Laboratory // All rights reserved. // // This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The // full copyright notice is contained in the file COPYRIGHT located at the root // of the PyCXX distribution. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // - Redistributions of source code must retain the above copyright notice, // this list of conditions and the disclaimer below. // - Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the disclaimer (as noted below) in the // documentation and/or materials provided with the distribution. // - Neither the name of the UC/LLNL nor the names of its contributors may be // used to endorse or promote products derived from this software without // specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF // CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH // DAMAGE. // //----------------------------------------------------------------------------- #ifndef __CXX_Exception_h #define __CXX_Exception_h #include "CXX/WrapPython.h" #include "CXX/Version.hxx" #include "CXX/Config.hxx" #include "CXX/IndirectPythonInterface.hxx" #include #include // This mimics the Python structure, in order to minimize confusion namespace Py { class ExtensionExceptionType; class Object; class Exception { public: Exception( ExtensionExceptionType &exception, const std::string& reason ); Exception( ExtensionExceptionType &exception, Object &reason ); explicit Exception () {} Exception (const std::string& reason) { PyErr_SetString (Py::_Exc_RuntimeError(), reason.c_str()); } Exception (PyObject* exception, const std::string& reason) { PyErr_SetString (exception, reason.c_str()); } Exception (PyObject* exception, Object &reason); void clear() // clear the error // technically but not philosophically const { PyErr_Clear(); } }; // Abstract class StandardError: public Exception { protected: explicit StandardError() {} }; class LookupError: public StandardError { protected: explicit LookupError() {} }; class ArithmeticError: public StandardError { protected: explicit ArithmeticError() {} }; class EnvironmentError: public StandardError { protected: explicit EnvironmentError() {} }; // Concrete class TypeError: public StandardError { public: TypeError (const std::string& reason) : StandardError() { PyErr_SetString (Py::_Exc_TypeError(),reason.c_str()); } }; class IndexError: public LookupError { public: IndexError (const std::string& reason) : LookupError() { PyErr_SetString (Py::_Exc_IndexError(), reason.c_str()); } }; class AttributeError: public StandardError { public: AttributeError (const std::string& reason) : StandardError() { PyErr_SetString (Py::_Exc_AttributeError(), reason.c_str()); } }; class NameError: public StandardError { public: NameError (const std::string& reason) : StandardError() { PyErr_SetString (Py::_Exc_NameError(), reason.c_str()); } }; class RuntimeError: public StandardError { public: RuntimeError (const std::string& reason) : StandardError() { PyErr_SetString (Py::_Exc_RuntimeError(), reason.c_str()); } }; class NotImplementedError: public StandardError { public: NotImplementedError (const std::string& reason) : StandardError() { PyErr_SetString (Py::_Exc_NotImplementedError(), reason.c_str()); } }; class SystemError: public StandardError { public: SystemError (const std::string& reason) : StandardError() { PyErr_SetString (Py::_Exc_SystemError(),reason.c_str()); } }; class KeyError: public LookupError { public: KeyError (const std::string& reason) : LookupError() { PyErr_SetString (Py::_Exc_KeyError(),reason.c_str()); } }; class ValueError: public StandardError { public: ValueError (const std::string& reason) : StandardError() { PyErr_SetString (Py::_Exc_ValueError(), reason.c_str()); } }; class OverflowError: public ArithmeticError { public: OverflowError (const std::string& reason) : ArithmeticError() { PyErr_SetString (Py::_Exc_OverflowError(), reason.c_str()); } }; class ZeroDivisionError: public ArithmeticError { public: ZeroDivisionError (const std::string& reason) : ArithmeticError() { PyErr_SetString (Py::_Exc_ZeroDivisionError(), reason.c_str()); } }; class FloatingPointError: public ArithmeticError { public: FloatingPointError (const std::string& reason) : ArithmeticError() { PyErr_SetString (Py::_Exc_FloatingPointError(), reason.c_str()); } }; class MemoryError: public StandardError { public: MemoryError (const std::string& reason) : StandardError() { PyErr_SetString (Py::_Exc_MemoryError(), reason.c_str()); } }; class SystemExit: public StandardError { public: SystemExit (const std::string& reason) : StandardError() { PyErr_SetString (Py::_Exc_SystemExit(),reason.c_str()); } }; }// Py #endif pycxx-6.2.5/CXX/Python2/ExtensionModule.hxx000644 000771 000000 00000021035 11722441226 021033 0ustar00barrywheel000000 000000 //----------------------------------------------------------------------------- // // Copyright (c) 1998 - 2007, The Regents of the University of California // Produced at the Lawrence Livermore National Laboratory // All rights reserved. // // This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The // full copyright notice is contained in the file COPYRIGHT located at the root // of the PyCXX distribution. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // - Redistributions of source code must retain the above copyright notice, // this list of conditions and the disclaimer below. // - Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the disclaimer (as noted below) in the // documentation and/or materials provided with the distribution. // - Neither the name of the UC/LLNL nor the names of its contributors may be // used to endorse or promote products derived from this software without // specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF // CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH // DAMAGE. // //----------------------------------------------------------------------------- #ifndef __CXX_ExtensionModule__h #define __CXX_ExtensionModule__h namespace Py { class ExtensionModuleBase { public: ExtensionModuleBase( const char *name ); virtual ~ExtensionModuleBase(); Module module( void ) const; // only valid after initialize() has been called Dict moduleDictionary( void ) const; // only valid after initialize() has been called virtual Object invoke_method_noargs( void *method_def ) = 0; virtual Object invoke_method_keyword( void *method_def, const Tuple &_args, const Dict &_keywords ) = 0; virtual Object invoke_method_varargs( void *method_def, const Tuple &_args ) = 0; const std::string &name() const; const std::string &fullName() const; // what is returned from PyInit_ function Object moduleObject( void ) const; protected: // Initialize the module void initialize( const char *module_doc ); const std::string m_module_name; const std::string m_full_module_name; MethodTable m_method_table; PyObject *m_module; private: // // prevent the compiler generating these unwanted functions // ExtensionModuleBase( const ExtensionModuleBase & ); //unimplemented void operator=( const ExtensionModuleBase & ); //unimplemented }; // Note: Python calls noargs as varargs buts args==NULL extern "C" PyObject *method_noargs_call_handler( PyObject *_self_and_name_tuple, PyObject * ); extern "C" PyObject *method_varargs_call_handler( PyObject *_self_and_name_tuple, PyObject *_args ); extern "C" PyObject *method_keyword_call_handler( PyObject *_self_and_name_tuple, PyObject *_args, PyObject *_keywords ); extern "C" void do_not_dealloc( void * ); template class ExtensionModule : public ExtensionModuleBase { public: ExtensionModule( const char *name ) : ExtensionModuleBase( name ) {} virtual ~ExtensionModule() {} protected: typedef Object (T::*method_noargs_function_t)(); typedef Object (T::*method_varargs_function_t)( const Tuple &args ); typedef Object (T::*method_keyword_function_t)( const Tuple &args, const Dict &kws ); typedef std::map *> method_map_t; static void add_noargs_method( const char *name, method_noargs_function_t function, const char *doc="" ) { method_map_t &mm = methods(); mm[ std::string( name ) ] = new MethodDefExt( name, function, method_noargs_call_handler, doc ); } static void add_varargs_method( const char *name, method_varargs_function_t function, const char *doc="" ) { method_map_t &mm = methods(); mm[ std::string( name ) ] = new MethodDefExt( name, function, method_varargs_call_handler, doc ); } static void add_keyword_method( const char *name, method_keyword_function_t function, const char *doc="" ) { method_map_t &mm = methods(); mm[ std::string( name ) ] = new MethodDefExt( name, function, method_keyword_call_handler, doc ); } void initialize( const char *module_doc="" ) { ExtensionModuleBase::initialize( module_doc ); Dict dict( moduleDictionary() ); // // put each of the methods into the modules dictionary // so that we get called back at the function in T. // method_map_t &mm = methods(); EXPLICIT_TYPENAME method_map_t::const_iterator i = mm.begin(); EXPLICIT_TYPENAME method_map_t::const_iterator i_end = mm.end(); for ( ; i != i_end; ++i ) { MethodDefExt *method_def = (*i).second; static PyObject *self = PyCObject_FromVoidPtr( this, do_not_dealloc ); Tuple args( 2 ); args[0] = Object( self, true ); args[1] = Object( PyCObject_FromVoidPtr( method_def, do_not_dealloc ), true ); PyObject *func = PyCFunction_New ( &method_def->ext_meth_def, new_reference_to( args ) ); method_def->py_method = Object( func, true ); dict[ (*i).first ] = method_def->py_method; } } protected: // Tom Malcolmson reports that derived classes need access to these static method_map_t &methods( void ) { static method_map_t *map_of_methods = NULL; if( map_of_methods == NULL ) map_of_methods = new method_map_t; return *map_of_methods; } // this invoke function must be called from within a try catch block virtual Object invoke_method_noargs( void *method_def ) { // cast up to the derived class, method_def and call T *self = static_cast( this ); MethodDefExt *meth_def = reinterpret_cast *>( method_def ); return (self->*meth_def->ext_noargs_function)(); } // this invoke function must be called from within a try catch block virtual Object invoke_method_varargs( void *method_def, const Tuple &args ) { // cast up to the derived class, method_def and call T *self = static_cast( this ); MethodDefExt *meth_def = reinterpret_cast *>( method_def ); return (self->*meth_def->ext_varargs_function)( args ); } // this invoke function must be called from within a try catch block virtual Object invoke_method_keyword( void *method_def, const Tuple &args, const Dict &keywords ) { // cast up to the derived class, method_def and call T *self = static_cast( this ); MethodDefExt *meth_def = reinterpret_cast *>( method_def ); return (self->*meth_def->ext_keyword_function)( args, keywords ); } private: // // prevent the compiler generating these unwanted functions // ExtensionModule( const ExtensionModule & ); //unimplemented void operator=( const ExtensionModule & ); //unimplemented }; } // Namespace Py // End of __CXX_ExtensionModule__h #endif pycxx-6.2.5/CXX/Python2/ExtensionOldType.hxx000644 000771 000000 00000031612 11615064135 021171 0ustar00barrywheel000000 000000 //----------------------------------------------------------------------------- // // Copyright (c) 1998 - 2007, The Regents of the University of California // Produced at the Lawrence Livermore National Laboratory // All rights reserved. // // This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The // full copyright notice is contained in the file COPYRIGHT located at the root // of the PyCXX distribution. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // - Redistributions of source code must retain the above copyright notice, // this list of conditions and the disclaimer below. // - Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the disclaimer (as noted below) in the // documentation and/or materials provided with the distribution. // - Neither the name of the UC/LLNL nor the names of its contributors may be // used to endorse or promote products derived from this software without // specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF // CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH // DAMAGE. // //----------------------------------------------------------------------------- #ifndef __CXX_ExtensionOldType__h #define __CXX_ExtensionOldType__h namespace Py { template class PythonExtension : public PythonExtensionBase { public: static PyTypeObject *type_object() { return behaviors().type_object(); } static bool check( PyObject *p ) { // is p like me? return p->ob_type == type_object(); } static bool check( const Object &ob ) { return check( ob.ptr() ); } // // every object needs getattr implemented // to support methods // virtual Object getattr( const char *name ) { return getattr_methods( name ); } PyObject *selfPtr() { return this; } Object self() { return asObject( this ); } protected: explicit PythonExtension() : PythonExtensionBase() { PyObject_Init( this, type_object() ); // every object must support getattr behaviors().supportGetattr(); } virtual ~PythonExtension() {} static PythonType &behaviors() { static PythonType* p; if( p == NULL ) { #if defined( _CPPRTTI ) || defined( __GNUG__ ) const char *default_name =( typeid( T ) ).name(); #else const char *default_name = "unknown"; #endif p = new PythonType( sizeof( T ), 0, default_name ); p->set_tp_dealloc( extension_object_deallocator ); } return *p; } typedef Object (T::*method_noargs_function_t)(); typedef Object (T::*method_varargs_function_t)( const Tuple &args ); typedef Object (T::*method_keyword_function_t)( const Tuple &args, const Dict &kws ); typedef std::map *> method_map_t; // support the default attributes, __name__, __doc__ and methods virtual Object getattr_default( const char *_name ) { std::string name( _name ); if( name == "__name__" && type_object()->tp_name != NULL ) { return Py::String( type_object()->tp_name ); } if( name == "__doc__" && type_object()->tp_doc != NULL ) { return Py::String( type_object()->tp_doc ); } // trying to fake out being a class for help() // else if( name == "__bases__" ) // { // return Py::Tuple( 0 ); // } // else if( name == "__module__" ) // { // return Py::Nothing(); // } // else if( name == "__dict__" ) // { // return Py::Dict(); // } return getattr_methods( _name ); } // turn a name into function object virtual Object getattr_methods( const char *_name ) { std::string name( _name ); method_map_t &mm = methods(); // see if name exists and get entry with method EXPLICIT_TYPENAME method_map_t::const_iterator i = mm.find( name ); if( i == mm.end() ) { if( name == "__methods__" ) { List methods; i = mm.begin(); EXPLICIT_TYPENAME method_map_t::const_iterator i_end = mm.end(); for( ; i != i_end; ++i ) methods.append( String( (*i).first ) ); return methods; } throw AttributeError( name ); } MethodDefExt *method_def = i->second; Tuple self( 2 ); self[0] = Object( this ); self[1] = Object( PyCObject_FromVoidPtr( method_def, do_not_dealloc ), true ); PyObject *func = PyCFunction_New( &method_def->ext_meth_def, self.ptr() ); return Object(func, true); } // check that all methods added are unique static void check_unique_method_name( const char *name ) { method_map_t &mm = methods(); EXPLICIT_TYPENAME method_map_t::const_iterator i; i = mm.find( name ); if( i != mm.end() ) throw AttributeError( name ); } static void add_noargs_method( const char *name, method_noargs_function_t function, const char *doc="" ) { check_unique_method_name( name ); method_map_t &mm = methods(); mm[ std::string( name ) ] = new MethodDefExt( name, function, method_noargs_call_handler, doc ); } static void add_varargs_method( const char *name, method_varargs_function_t function, const char *doc="" ) { check_unique_method_name( name ); method_map_t &mm = methods(); mm[ std::string( name ) ] = new MethodDefExt( name, function, method_varargs_call_handler, doc ); } static void add_keyword_method( const char *name, method_keyword_function_t function, const char *doc="" ) { check_unique_method_name( name ); method_map_t &mm = methods(); mm[ std::string( name ) ] = new MethodDefExt( name, function, method_keyword_call_handler, doc ); } private: static method_map_t &methods( void ) { static method_map_t *map_of_methods = NULL; if( map_of_methods == NULL ) map_of_methods = new method_map_t; return *map_of_methods; } // Note: Python calls noargs as varargs buts args==NULL static PyObject *method_noargs_call_handler( PyObject *_self_and_name_tuple, PyObject * ) { try { Tuple self_and_name_tuple( _self_and_name_tuple ); PyObject *self_in_cobject = self_and_name_tuple[0].ptr(); T *self = static_cast( self_in_cobject ); MethodDefExt *meth_def = reinterpret_cast *>( PyCObject_AsVoidPtr( self_and_name_tuple[1].ptr() ) ); Object result; // Adding try & catch in case of STL debug-mode exceptions. #ifdef _STLP_DEBUG try { result = (self->*meth_def->ext_noargs_function)(); } catch( std::__stl_debug_exception ) { // throw cxx::RuntimeError( sErrMsg ); throw RuntimeError( "Error message not set yet." ); } #else result = (self->*meth_def->ext_noargs_function)(); #endif // _STLP_DEBUG return new_reference_to( result.ptr() ); } catch( Exception & ) { return 0; } } static PyObject *method_varargs_call_handler( PyObject *_self_and_name_tuple, PyObject *_args ) { try { Tuple self_and_name_tuple( _self_and_name_tuple ); PyObject *self_in_cobject = self_and_name_tuple[0].ptr(); T *self = static_cast( self_in_cobject ); MethodDefExt *meth_def = reinterpret_cast *>( PyCObject_AsVoidPtr( self_and_name_tuple[1].ptr() ) ); Tuple args( _args ); Object result; // Adding try & catch in case of STL debug-mode exceptions. #ifdef _STLP_DEBUG try { result = (self->*meth_def->ext_varargs_function)( args ); } catch( std::__stl_debug_exception ) { throw RuntimeError( "Error message not set yet." ); } #else result = (self->*meth_def->ext_varargs_function)( args ); #endif // _STLP_DEBUG return new_reference_to( result.ptr() ); } catch( Exception & ) { return 0; } } static PyObject *method_keyword_call_handler( PyObject *_self_and_name_tuple, PyObject *_args, PyObject *_keywords ) { try { Tuple self_and_name_tuple( _self_and_name_tuple ); PyObject *self_in_cobject = self_and_name_tuple[0].ptr(); T *self = static_cast( self_in_cobject ); MethodDefExt *meth_def = reinterpret_cast *>( PyCObject_AsVoidPtr( self_and_name_tuple[1].ptr() ) ); Tuple args( _args ); // _keywords may be NULL so be careful about the way the dict is created Dict keywords; if( _keywords != NULL ) keywords = Dict( _keywords ); Object result( ( self->*meth_def->ext_keyword_function )( args, keywords ) ); return new_reference_to( result.ptr() ); } catch( Exception & ) { return 0; } } static void extension_object_deallocator( PyObject* t ) { delete (T *)( t ); } // // prevent the compiler generating these unwanted functions // explicit PythonExtension( const PythonExtension &other ); void operator=( const PythonExtension &rhs ); }; // // ExtensionObject is an Object that will accept only T's. // template class ExtensionObject: public Object { public: explicit ExtensionObject( PyObject *pyob ) : Object( pyob ) { validate(); } ExtensionObject( const ExtensionObject &other ) : Object( *other ) { validate(); } ExtensionObject( const Object &other ) : Object( *other ) { validate(); } ExtensionObject &operator=( const Object &rhs ) { return( *this = *rhs ); } ExtensionObject &operator=( PyObject *rhsp ) { if( ptr() != rhsp ) set( rhsp ); return *this; } virtual bool accepts( PyObject *pyob ) const { return( pyob && T::check( pyob ) ); } // // Obtain a pointer to the PythonExtension object // T *extensionObject( void ) { return static_cast( ptr() ); } }; } // Namespace Py // End of __CXX_ExtensionOldType__h #endif pycxx-6.2.5/CXX/Python2/Extensions.hxx000644 000771 000000 00000015652 11230627123 020054 0ustar00barrywheel000000 000000 //----------------------------------------------------------------------------- // // Copyright (c) 1998 - 2007, The Regents of the University of California // Produced at the Lawrence Livermore National Laboratory // All rights reserved. // // This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The // full copyright notice is contained in the file COPYRIGHT located at the root // of the PyCXX distribution. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // - Redistributions of source code must retain the above copyright notice, // this list of conditions and the disclaimer below. // - Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the disclaimer (as noted below) in the // documentation and/or materials provided with the distribution. // - Neither the name of the UC/LLNL nor the names of its contributors may be // used to endorse or promote products derived from this software without // specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF // CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH // DAMAGE. // //----------------------------------------------------------------------------- #ifndef __CXX_Extensions__h #define __CXX_Extensions__h #ifdef _MSC_VER // disable warning C4786: symbol greater than 255 character, // okay to ignore #pragma warning( disable: 4786 ) #endif #include "CXX/WrapPython.h" #include "CXX/Version.hxx" #include "CXX/Python2/Config.hxx" #include "CXX/Python2/CxxDebug.hxx" #include "CXX/Python2/Objects.hxx" extern "C" { extern PyObject py_object_initializer; } #include #include // ---------------------------------------------------------------------- namespace Py { class ExtensionModuleBase; // Make an Exception Type for use in raising custom exceptions class ExtensionExceptionType : public Object { public: ExtensionExceptionType(); virtual ~ExtensionExceptionType(); // call init to create the type void init( ExtensionModuleBase &module, const std::string &name, ExtensionExceptionType &parent ); void init( ExtensionModuleBase &module, const std::string &name ); }; class MethodTable { public: MethodTable(); virtual ~MethodTable(); void add( const char *method_name, PyCFunction f, const char *doc="", int flag=1 ); PyMethodDef *table(); protected: std::vector t; // accumulator of PyMethodDef's PyMethodDef *mt; // Actual method table produced when full static PyMethodDef method( const char* method_name, PyCFunction f, int flags=1, const char* doc="" ); private: // // prevent the compiler generating these unwanted functions // MethodTable( const MethodTable &m ); //unimplemented void operator=( const MethodTable &m ); //unimplemented }; // end class MethodTable // Note: Python calls noargs as varargs buts args==NULL extern "C" typedef PyObject *(*method_noargs_call_handler_t)( PyObject *_self, PyObject * ); extern "C" typedef PyObject *(*method_varargs_call_handler_t)( PyObject *_self, PyObject *_args ); extern "C" typedef PyObject *(*method_keyword_call_handler_t)( PyObject *_self, PyObject *_args, PyObject *_dict ); template class MethodDefExt : public PyMethodDef { public: typedef Object (T::*method_noargs_function_t)(); typedef Object (T::*method_varargs_function_t)( const Tuple &args ); typedef Object (T::*method_keyword_function_t)( const Tuple &args, const Dict &kws ); // NOARGS MethodDefExt ( const char *_name, method_noargs_function_t _function, method_noargs_call_handler_t _handler, const char *_doc ) { ext_meth_def.ml_name = const_cast( _name ); ext_meth_def.ml_meth = reinterpret_cast( _handler ); ext_meth_def.ml_flags = METH_NOARGS; ext_meth_def.ml_doc = const_cast( _doc ); ext_noargs_function = _function; ext_varargs_function = NULL; ext_keyword_function = NULL; } // VARARGS MethodDefExt ( const char *_name, method_varargs_function_t _function, method_varargs_call_handler_t _handler, const char *_doc ) { ext_meth_def.ml_name = const_cast( _name ); ext_meth_def.ml_meth = reinterpret_cast( _handler ); ext_meth_def.ml_flags = METH_VARARGS; ext_meth_def.ml_doc = const_cast( _doc ); ext_noargs_function = NULL; ext_varargs_function = _function; ext_keyword_function = NULL; } // VARARGS + KEYWORD MethodDefExt ( const char *_name, method_keyword_function_t _function, method_keyword_call_handler_t _handler, const char *_doc ) { ext_meth_def.ml_name = const_cast( _name ); ext_meth_def.ml_meth = reinterpret_cast( _handler ); ext_meth_def.ml_flags = METH_VARARGS|METH_KEYWORDS; ext_meth_def.ml_doc = const_cast( _doc ); ext_noargs_function = NULL; ext_varargs_function = NULL; ext_keyword_function = _function; } ~MethodDefExt() {} PyMethodDef ext_meth_def; method_noargs_function_t ext_noargs_function; method_varargs_function_t ext_varargs_function; method_keyword_function_t ext_keyword_function; Object py_method; }; } // Namespace Py #include "CXX/Python2/ExtensionModule.hxx" #include "CXX/Python2/PythonType.hxx" #include "CXX/Python2/ExtensionTypeBase.hxx" #include "CXX/Python2/ExtensionOldType.hxx" #include "CXX/Python2/ExtensionType.hxx" // End of CXX_Extensions.h #endif pycxx-6.2.5/CXX/Python2/ExtensionType.hxx000644 000771 000000 00000033144 11367330334 020535 0ustar00barrywheel000000 000000 //----------------------------------------------------------------------------- // // Copyright (c) 1998 - 2007, The Regents of the University of California // Produced at the Lawrence Livermore National Laboratory // All rights reserved. // // This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The // full copyright notice is contained in the file COPYRIGHT located at the root // of the PyCXX distribution. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // - Redistributions of source code must retain the above copyright notice, // this list of conditions and the disclaimer below. // - Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the disclaimer (as noted below) in the // documentation and/or materials provided with the distribution. // - Neither the name of the UC/LLNL nor the names of its contributors may be // used to endorse or promote products derived from this software without // specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF // CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH // DAMAGE. // //----------------------------------------------------------------------------- #ifndef __CXX_ExtensionClass__h #define __CXX_ExtensionClass__h #define PYCXX_NOARGS_METHOD_NAME( NAME ) _callNoArgsMethod__##NAME #define PYCXX_VARARGS_METHOD_NAME( NAME ) _callVarArgsMethod__##NAME #define PYCXX_KEYWORDS_METHOD_NAME( NAME ) _callKeywordsMethod__##NAME #define PYCXX_NOARGS_METHOD_DECL( CLS, NAME ) \ static PyObject *PYCXX_NOARGS_METHOD_NAME( NAME )( PyObject *_self, PyObject *, PyObject * ) \ { \ try \ { \ Py::PythonClassInstance *self_python = reinterpret_cast< Py::PythonClassInstance * >( _self ); \ CLS *self = reinterpret_cast< CLS * >( self_python->m_pycxx_object ); \ Py::Object r( (self->NAME)() ); \ return Py::new_reference_to( r.ptr() ); \ } \ catch( Py::Exception & ) \ { \ return 0; \ } \ } #define PYCXX_VARARGS_METHOD_DECL( CLS, NAME ) \ static PyObject *PYCXX_VARARGS_METHOD_NAME( NAME )( PyObject *_self, PyObject *_a, PyObject * ) \ { \ try \ { \ Py::PythonClassInstance *self_python = reinterpret_cast< Py::PythonClassInstance * >( _self ); \ CLS *self = reinterpret_cast< CLS * >( self_python->m_pycxx_object ); \ Py::Tuple a( _a ); \ Py::Object r( (self->NAME)( a ) ); \ return Py::new_reference_to( r.ptr() ); \ } \ catch( Py::Exception & ) \ { \ return 0; \ } \ } #define PYCXX_KEYWORDS_METHOD_DECL( CLS, NAME ) \ static PyObject *PYCXX_KEYWORDS_METHOD_NAME( NAME )( PyObject *_self, PyObject *_a, PyObject *_k ) \ { \ try \ { \ Py::PythonClassInstance *self_python = reinterpret_cast< Py::PythonClassInstance * >( _self ); \ CLS *self = reinterpret_cast< CLS * >( self_python->m_pycxx_object ); \ Py::Tuple a( _a ); \ Py::Dict k; \ if( _k != NULL ) \ k = _k; \ Py::Object r( (self->NAME)( a, k ) ); \ return Py::new_reference_to( r.ptr() ); \ } \ catch( Py::Exception & ) \ { \ return 0; \ } \ } // need to support METH_STATIC and METH_CLASS #define PYCXX_ADD_NOARGS_METHOD( PYNAME, NAME, docs ) \ add_method( #PYNAME, (PyCFunction)PYCXX_NOARGS_METHOD_NAME( NAME ), METH_NOARGS, docs ) #define PYCXX_ADD_VARARGS_METHOD( PYNAME, NAME, docs ) \ add_method( #PYNAME, (PyCFunction)PYCXX_VARARGS_METHOD_NAME( NAME ), METH_VARARGS, docs ) #define PYCXX_ADD_KEYWORDS_METHOD( PYNAME, NAME, docs ) \ add_method( #PYNAME, (PyCFunction)PYCXX_KEYWORDS_METHOD_NAME( NAME ), METH_VARARGS | METH_KEYWORDS, docs ) namespace Py { extern PythonExtensionBase *getPythonExtensionBase( PyObject *self ); struct PythonClassInstance { PyObject_HEAD PythonExtensionBase *m_pycxx_object; }; class ExtensionClassMethodsTable { public: ExtensionClassMethodsTable() : m_methods_table( new PyMethodDef[ METHOD_TABLE_SIZE_INCREMENT ] ) , m_methods_used( 0 ) , m_methods_size( METHOD_TABLE_SIZE_INCREMENT ) { } ~ExtensionClassMethodsTable() { delete m_methods_table; } // check that all methods added are unique void check_unique_method_name( const char *_name ) { std::string name( _name ); for( int i=0; iml_name = const_cast( name ); p->ml_meth = function; p->ml_flags = flags; p->ml_doc = const_cast( doc ); m_methods_used++; p++; // add the sentinel marking the table end p->ml_name = NULL; p->ml_meth = NULL; p->ml_flags = 0; p->ml_doc = NULL; return m_methods_table; } private: enum {METHOD_TABLE_SIZE_INCREMENT = 1}; PyMethodDef *m_methods_table; int m_methods_used; int m_methods_size; }; template class PythonClass : public PythonExtensionBase { protected: explicit PythonClass( PythonClassInstance *self, Tuple &args, Dict &kwds ) : PythonExtensionBase() , m_class_instance( self ) { } virtual ~PythonClass() {} static ExtensionClassMethodsTable &methodTable() { static ExtensionClassMethodsTable *method_table; if( method_table == NULL ) method_table = new ExtensionClassMethodsTable; return *method_table; } static void add_method( const char *name, PyCFunction function, int flags, const char *doc=NULL ) { behaviors().set_methods( methodTable().add_method( name, function, flags, doc ) ); } static PythonType &behaviors() { static PythonType *p; if( p == NULL ) { #if defined( _CPPRTTI ) || defined( __GNUG__ ) const char *default_name = (typeid( T )).name(); #else const char *default_name = "unknown"; #endif p = new PythonType( sizeof( T ), 0, default_name ); p->set_tp_new( extension_object_new ); p->set_tp_init( extension_object_init ); p->set_tp_dealloc( extension_object_deallocator ); // we are a class p->supportClass(); // always support get and set attr p->supportGetattro(); p->supportSetattro(); } return *p; } static PyObject *extension_object_new( PyTypeObject *subtype, PyObject *args, PyObject *kwds ) { #ifdef PYCXX_DEBUG std::cout << "extension_object_new()" << std::endl; #endif PythonClassInstance *o = reinterpret_cast( subtype->tp_alloc( subtype, 0 ) ); if( o == NULL ) return NULL; o->m_pycxx_object = NULL; PyObject *self = reinterpret_cast( o ); #ifdef PYCXX_DEBUG std::cout << "extension_object_new() => self=0x" << std::hex << reinterpret_cast< unsigned int >( self ) << std::dec << std::endl; #endif return self; } static int extension_object_init( PyObject *_self, PyObject *args_, PyObject *kwds_ ) { try { Py::Tuple args( args_ ); Py::Dict kwds; if( kwds_ != NULL ) kwds = kwds_; PythonClassInstance *self = reinterpret_cast( _self ); #ifdef PYCXX_DEBUG std::cout << "extension_object_init( self=0x" << std::hex << reinterpret_cast< unsigned int >( self ) << std::dec << " )" << std::endl; std::cout << " self->m_pycxx_object=0x" << std::hex << reinterpret_cast< unsigned int >( self->m_pycxx_object ) << std::dec << std::endl; #endif if( self->m_pycxx_object == NULL ) { self->m_pycxx_object = new T( self, args, kwds ); #ifdef PYCXX_DEBUG std::cout << " self->m_pycxx_object=0x" << std::hex << reinterpret_cast< unsigned int >( self->m_pycxx_object ) << std::dec << std::endl; #endif } else { #ifdef PYCXX_DEBUG std::cout << " reinit - self->m_pycxx_object=0x" << std::hex << reinterpret_cast< unsigned int >( self->m_pycxx_object ) << std::dec << std::endl; #endif self->m_pycxx_object->reinit( args, kwds ); } } catch( Exception & ) { return -1; } return 0; } static void extension_object_deallocator( PyObject *_self ) { PythonClassInstance *self = reinterpret_cast< PythonClassInstance * >( _self ); #ifdef PYCXX_DEBUG std::cout << "extension_object_deallocator( self=0x" << std::hex << reinterpret_cast< unsigned int >( self ) << std::dec << " )" << std::endl; std::cout << " self->m_pycxx_object=0x" << std::hex << reinterpret_cast< unsigned int >( self->m_pycxx_object ) << std::dec << std::endl; #endif delete self->m_pycxx_object; _self->ob_type->tp_free( _self ); } public: static PyTypeObject *type_object() { return behaviors().type_object(); } static Object type() { return Object( reinterpret_cast( behaviors().type_object() ) ); } static bool check( PyObject *p ) { // is p like me? return p->ob_type == type_object(); } static bool check( const Object &ob ) { return check( ob.ptr() ); } virtual PyObject *selfPtr() { return reinterpret_cast( m_class_instance ); } virtual Object self() { return Object( reinterpret_cast( m_class_instance ) ); } protected: private: PythonClassInstance *m_class_instance; private: // // prevent the compiler generating these unwanted functions // explicit PythonClass( const PythonClass &other ); void operator=( const PythonClass &rhs ); }; // // ExtensionObject is an Object that will accept only T's. // template class PythonClassObject: public Object { public: explicit PythonClassObject( PyObject *pyob ) : Object( pyob ) { validate(); } PythonClassObject( const PythonClassObject &other ) : Object( *other ) { validate(); } PythonClassObject( const Object &other ) : Object( *other ) { validate(); } PythonClassObject &operator=( const Object &rhs ) { *this = *rhs; return *this; } PythonClassObject &operator=( PyObject *rhsp ) { if( ptr() != rhsp ) set( rhsp ); return *this; } virtual bool accepts( PyObject *pyob ) const { return( pyob && T::check( pyob ) ); } // // Obtain a pointer to the PythonExtension object // T *getCxxObject( void ) { return dynamic_cast< T * >( getPythonExtensionBase( ptr() ) ); } }; } // Namespace Py // End of __CXX_ExtensionClass__h #endif pycxx-6.2.5/CXX/Python2/ExtensionTypeBase.hxx000644 000771 000000 00000020342 11722441226 021322 0ustar00barrywheel000000 000000 //----------------------------------------------------------------------------- // // Copyright (c) 1998 - 2007, The Regents of the University of California // Produced at the Lawrence Livermore National Laboratory // All rights reserved. // // This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The // full copyright notice is contained in the file COPYRIGHT located at the root // of the PyCXX distribution. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // - Redistributions of source code must retain the above copyright notice, // this list of conditions and the disclaimer below. // - Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the disclaimer (as noted below) in the // documentation and/or materials provided with the distribution. // - Neither the name of the UC/LLNL nor the names of its contributors may be // used to endorse or promote products derived from this software without // specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF // CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH // DAMAGE. // //----------------------------------------------------------------------------- #ifndef __CXX_ExtensionTypeBase__h #define __CXX_ExtensionTypeBase__h namespace Py { // Class PythonExtension is what you inherit from to create // a new Python extension type. You give your class itself // as the template paramter. // There are two ways that extension objects can get destroyed. // 1. Their reference count goes to zero // 2. Someone does an explicit delete on a pointer. // In(1) the problem is to get the destructor called // We register a special deallocator in the Python type object // (see behaviors()) to do this. // In(2) there is no problem, the dtor gets called. // PythonExtension does not use the usual Python heap allocator, // instead using new/delete. We do the setting of the type object // and reference count, usually done by PyObject_New, in the // base class ctor. // This special deallocator does a delete on the pointer. class PythonExtensionBase : public PyObject { public: PythonExtensionBase(); virtual ~PythonExtensionBase(); public: // object virtual void reinit( Tuple &args, Dict &kwds ); // object basics virtual int print( FILE *, int ); virtual Object getattr( const char * ); virtual int setattr( const char *, const Object & ); virtual Object getattro( const String & ); Object genericGetAttro( const String & ); virtual int setattro( const String &, const Object & ); int genericSetAttro( const String &, const Object & ); virtual int compare( const Object & ); virtual Object rich_compare( const Object &, int ); virtual Object repr(); virtual Object str(); virtual long hash(); virtual Object call( const Object &, const Object & ); virtual Object iter(); virtual PyObject *iternext(); // Sequence methods virtual int sequence_length(); virtual Object sequence_concat( const Object & ); virtual Object sequence_repeat( Py_ssize_t ); virtual Object sequence_item( Py_ssize_t ); virtual Object sequence_slice( Py_ssize_t, Py_ssize_t ); virtual int sequence_ass_item( Py_ssize_t, const Object & ); virtual int sequence_ass_slice( Py_ssize_t, Py_ssize_t, const Object & ); // Mapping virtual int mapping_length(); virtual Object mapping_subscript( const Object & ); virtual int mapping_ass_subscript( const Object &, const Object & ); // Number virtual int number_nonzero(); virtual Object number_negative(); virtual Object number_positive(); virtual Object number_absolute(); virtual Object number_invert(); virtual Object number_int(); virtual Object number_float(); virtual Object number_long(); virtual Object number_oct(); virtual Object number_hex(); virtual Object number_add( const Object & ); virtual Object number_subtract( const Object & ); virtual Object number_multiply( const Object & ); virtual Object number_divide( const Object & ); virtual Object number_remainder( const Object & ); virtual Object number_divmod( const Object & ); virtual Object number_lshift( const Object & ); virtual Object number_rshift( const Object & ); virtual Object number_and( const Object & ); virtual Object number_xor( const Object & ); virtual Object number_or( const Object & ); virtual Object number_power( const Object &, const Object & ); // Buffer virtual Py_ssize_t buffer_getreadbuffer( Py_ssize_t, void** ); virtual Py_ssize_t buffer_getwritebuffer( Py_ssize_t, void** ); virtual Py_ssize_t buffer_getsegcount( Py_ssize_t* ); public: // helper functions to call function fn_name with 0 to 9 args Object callOnSelf( const std::string &fn_name ); Object callOnSelf( const std::string &fn_name, const Object &arg1 ); Object callOnSelf( const std::string &fn_name, const Object &arg1, const Object &arg2 ); Object callOnSelf( const std::string &fn_name, const Object &arg1, const Object &arg2, const Object &arg3 ); Object callOnSelf( const std::string &fn_name, const Object &arg1, const Object &arg2, const Object &arg3, const Object &arg4 ); Object callOnSelf( const std::string &fn_name, const Object &arg1, const Object &arg2, const Object &arg3, const Object &arg4, const Object &arg5 ); Object callOnSelf( const std::string &fn_name, const Object &arg1, const Object &arg2, const Object &arg3, const Object &arg4, const Object &arg5, const Object &arg6 ); Object callOnSelf( const std::string &fn_name, const Object &arg1, const Object &arg2, const Object &arg3, const Object &arg4, const Object &arg5, const Object &arg6, const Object &arg7 ); Object callOnSelf( const std::string &fn_name, const Object &arg1, const Object &arg2, const Object &arg3, const Object &arg4, const Object &arg5, const Object &arg6, const Object &arg7, const Object &arg8 ); Object callOnSelf( const std::string &fn_name, const Object &arg1, const Object &arg2, const Object &arg3, const Object &arg4, const Object &arg5, const Object &arg6, const Object &arg7, const Object &arg8, const Object &arg9 ); public: virtual PyObject *selfPtr() = 0; virtual Object self() = 0; private: void missing_method( void ); static PyObject *method_call_handler( PyObject *self, PyObject *args ); }; } // Namespace Py // End of __CXX_ExtensionTypeBase__h #endif pycxx-6.2.5/CXX/Python2/IndirectPythonInterface.hxx000644 000771 000000 00000013214 11205075152 022472 0ustar00barrywheel000000 000000 //----------------------------------------------------------------------------- // // Copyright (c) 1998 - 2007, The Regents of the University of California // Produced at the Lawrence Livermore National Laboratory // All rights reserved. // // This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The // full copyright notice is contained in the file COPYRIGHT located at the root // of the PyCXX distribution. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // - Redistributions of source code must retain the above copyright notice, // this list of conditions and the disclaimer below. // - Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the disclaimer (as noted below) in the // documentation and/or materials provided with the distribution. // - Neither the name of the UC/LLNL nor the names of its contributors may be // used to endorse or promote products derived from this software without // specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF // CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH // DAMAGE. // //----------------------------------------------------------------------------- #ifndef __CXX_INDIRECT_PYTHON_INTERFACE__HXX__ #define __CXX_INDIRECT_PYTHON_INTERFACE__HXX__ #include "CXX/WrapPython.h" namespace Py { bool InitialisePythonIndirectInterface(); // // Wrap Exception variables as function calls // PyObject * _Exc_Exception(); PyObject * _Exc_StandardError(); PyObject * _Exc_ArithmeticError(); PyObject * _Exc_LookupError(); PyObject * _Exc_AssertionError(); PyObject * _Exc_AttributeError(); PyObject * _Exc_EOFError(); PyObject * _Exc_FloatingPointError(); PyObject * _Exc_EnvironmentError(); PyObject * _Exc_IOError(); PyObject * _Exc_OSError(); PyObject * _Exc_ImportError(); PyObject * _Exc_IndexError(); PyObject * _Exc_KeyError(); PyObject * _Exc_KeyboardInterrupt(); PyObject * _Exc_MemoryError(); PyObject * _Exc_NameError(); PyObject * _Exc_OverflowError(); PyObject * _Exc_RuntimeError(); PyObject * _Exc_NotImplementedError(); PyObject * _Exc_SyntaxError(); PyObject * _Exc_SystemError(); PyObject * _Exc_SystemExit(); PyObject * _Exc_TypeError(); PyObject * _Exc_ValueError(); PyObject * _Exc_ZeroDivisionError(); #ifdef MS_WINDOWS PyObject * _Exc_WindowsError(); #endif PyObject * _Exc_MemoryErrorInst(); #if PY_MAJOR_VERSION >= 2 PyObject * _Exc_IndentationError(); PyObject * _Exc_TabError(); PyObject * _Exc_UnboundLocalError(); PyObject * _Exc_UnicodeError(); #endif // // Wrap Object variables as function calls // PyObject * _None(); PyObject * _False(); PyObject * _True(); // // Wrap Type variables as function calls // PyTypeObject * _List_Type(); bool _List_Check( PyObject *o ); PyTypeObject * _Buffer_Type(); bool _Buffer_Check( PyObject *op ); PyTypeObject * _Class_Type(); bool _Class_Check( PyObject *op ); PyTypeObject * _Instance_Type(); bool _Instance_Check( PyObject *op ); PyTypeObject * _Method_Type(); bool _Method_Check( PyObject *op ); PyTypeObject * _CObject_Type(); bool _CObject_Check( PyObject *op ); PyTypeObject * _Complex_Type(); bool _Complex_Check( PyObject *op ); PyTypeObject * _Dict_Type(); bool _Dict_Check( PyObject *op ); PyTypeObject * _File_Type(); bool _File_Check( PyObject *op ); PyTypeObject * _Float_Type(); bool _Float_Check( PyObject *op ); PyTypeObject * _Frame_Type(); bool _Frame_Check( PyObject *op ); PyTypeObject * _Function_Type(); bool _Function_Check( PyObject *op ); PyTypeObject * _Bool_Type(); bool _Boolean_Check( PyObject *op ); PyTypeObject * _Int_Type(); bool _Int_Check( PyObject *op ); PyTypeObject * _List_Type(); bool _List_Check( PyObject *op ); PyTypeObject * _Long_Type(); bool _Long_Check( PyObject *op ); PyTypeObject * _CFunction_Type(); bool _CFunction_Check( PyObject *op ); PyTypeObject * _Module_Type(); bool _Module_Check( PyObject *op ); PyTypeObject * _Type_Type(); bool _Type_Check( PyObject *op ); PyTypeObject * _Range_Type(); bool _Range_Check( PyObject *op ); PyTypeObject * _Slice_Type(); bool _Slice_Check( PyObject *op ); PyTypeObject * _String_Type(); bool _String_Check( PyObject *op ); PyTypeObject * _Unicode_Type(); bool _Unicode_Check( PyObject *op ); PyTypeObject * _TraceBack_Type(); bool _TraceBack_Check( PyObject *v ); PyTypeObject * _Tuple_Type(); bool _Tuple_Check( PyObject *op ); #if PY_MAJOR_VERSION >= 2 PyTypeObject * _Unicode_Type(); bool _Unicode_Check( PyObject *op ); #endif int &_Py_DebugFlag(); int &_Py_InteractiveFlag(); int &_Py_OptimizeFlag(); int &_Py_NoSiteFlag(); int &_Py_TabcheckFlag(); int &_Py_VerboseFlag(); #if PY_MAJOR_VERSION >= 2 int &_Py_UnicodeFlag(); #endif void _XINCREF( PyObject *op ); void _XDECREF( PyObject *op ); char *__Py_PackageContext(); } #endif // __CXX_INDIRECT_PYTHON_INTERFACE__HXX__ pycxx-6.2.5/CXX/Python2/Objects.hxx000644 000771 000000 00000270550 11523511652 017312 0ustar00barrywheel000000 000000 //----------------------------------------------------------------------------- // // Copyright (c) 1998 - 2007, The Regents of the University of California // Produced at the Lawrence Livermore National Laboratory // All rights reserved. // // This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The // full copyright notice is contained in the file COPYRIGHT located at the root // of the PyCXX distribution. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // - Redistributions of source code must retain the above copyright notice, // this list of conditions and the disclaimer below. // - Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the disclaimer (as noted below) in the // documentation and/or materials provided with the distribution. // - Neither the name of the UC/LLNL nor the names of its contributors may be // used to endorse or promote products derived from this software without // specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF // CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH // DAMAGE. // //----------------------------------------------------------------------------- #ifndef __CXX_Objects__h #define __CXX_Objects__h #include "CXX/WrapPython.h" #include "CXX/Version.hxx" #include "CXX/Config.hxx" #include "CXX/Exception.hxx" #include #include STR_STREAM #include #include #include #include namespace Py { typedef int sequence_index_type; // type of an index into a sequence // Forward declarations class Object; class Type; template class SeqBase; class String; class List; template class MapBase; class Tuple; class Dict; // new_reference_to also overloaded below on Object inline PyObject* new_reference_to(PyObject* p) { Py::_XINCREF(p); return p; } // returning Null() from an extension method triggers a // Python exception inline PyObject* Null() { return (static_cast(0)); } //===========================================================================// // class Object // The purpose of this class is to serve as the most general kind of // Python object, for the purpose of writing C++ extensions in Python // Objects hold a PyObject* which they own. This pointer is always a // valid pointer to a Python object. In children we must maintain this behavior. // // Instructions on how to make your own class MyType descended from Object: // (0) Pick a base class, either Object or perhaps SeqBase or MapBase. // This example assumes Object. // (1) Write a routine int MyType_Check (PyObject *) modeled after PyInt_Check, // PyFloat_Check, etc. // (2) Add method accepts: // virtual bool accepts (PyObject *pyob) const { // return pyob && MyType_Check (pyob); // } // (3) Include the following constructor and copy constructor // /* explicit MyType (PyObject *pyob): Object(pyob) { validate(); } MyType(const Object& other): Object(other.ptr()) { validate(); } */ // Alernate version for the constructor to allow for construction from owned pointers: /* explicit MyType (PyObject *pyob): Object(pyob) { validate(); } */ // You may wish to add other constructors; see the classes below for examples. // Each constructor must use "set" to set the pointer // and end by validating the pointer you have created. // (4) Each class needs at least these two assignment operators: /* MyType& operator= (const Object& rhs) { return (*this = *rhs); } Mytype& operator= (PyObject* rhsp) { if(ptr() == rhsp) return *this; set(rhsp); return *this; } */ // Note on accepts: constructors call the base class // version of a virtual when calling the base class constructor, // so the test has to be done explicitly in a descendent. // If you are inheriting from PythonExtension to define an object // note that it contains PythonExtension::check // which you can use in accepts when writing a wrapper class. // See Demo/range.h and Demo/range.cxx for an example. class Object { private: // the pointer to the Python object // Only Object sets this directly. // The default constructor for Object sets it to Py_None and // child classes must use "set" to set it // PyObject* p; protected: void set (PyObject* pyob, bool owned = false) { release(); p = pyob; if (!owned) { Py::_XINCREF (p); } validate(); } void release () { Py::_XDECREF (p); p = 0; } void validate(); public: // Constructor acquires new ownership of pointer unless explicitly told not to. explicit Object (PyObject* pyob=Py::_None(), bool owned = false): p (pyob) { if(!owned) { Py::_XINCREF (p); } validate(); } // Copy constructor acquires new ownership of pointer Object (const Object& ob): p(ob.p) { Py::_XINCREF (p); validate(); } // Assignment acquires new ownership of pointer Object& operator= (const Object& rhs) { set(rhs.p); return *this; } Object& operator= (PyObject* rhsp) { if(ptr() == rhsp) return *this; set (rhsp); return *this; } // Destructor virtual ~Object () { release (); } // Loaning the pointer to others, retain ownership PyObject* operator* () const { return p; } // Explicit reference_counting changes void increment_reference_count() { Py::_XINCREF(p); } void decrement_reference_count() { // not allowed to commit suicide, however if(reference_count() == 1) throw RuntimeError("Object::decrement_reference_count error."); Py::_XDECREF(p); } // Would like to call this pointer() but messes up STL in SeqBase PyObject* ptr () const { return p; } // // Queries // // Can pyob be used in this object's constructor? virtual bool accepts (PyObject *pyob) const { return (pyob != 0); } Py_ssize_t reference_count () const { // the reference count return p ? p->ob_refcnt : 0; } Type type () const; // the type object associated with this one String str () const; // the str() representation std::string as_string() const; String repr () const; // the repr () representation List dir () const; // the dir() list bool hasAttr (const std::string& s) const { return PyObject_HasAttrString (p, const_cast(s.c_str())) ? true: false; } Object getAttr (const std::string& s) const { return Object (PyObject_GetAttrString (p, const_cast(s.c_str())), true); } Object callMemberFunction( const std::string &function_name ) const; Object callMemberFunction( const std::string &function_name, const Tuple &args ) const; Object callMemberFunction( const std::string &function_name, const Tuple &args, const Dict &kw ) const; Object getItem (const Object& key) const { return Object (PyObject_GetItem(p, *key), true); } long hashValue () const { return PyObject_Hash (p); } // // int print (FILE* fp, int flags=Py_Print_RAW) //{ // return PyObject_Print (p, fp, flags); //} // bool is(PyObject *pother) const { // identity test return p == pother; } bool is(const Object& other) const { // identity test return p == other.p; } bool isNone() const { return p == _None(); } bool isCallable () const { return PyCallable_Check (p) != 0; } bool isInstance () const { return PyInstance_Check (p) != 0; } bool isDict () const { return Py::_Dict_Check (p); } bool isList () const { return Py::_List_Check (p); } bool isMapping () const { return PyMapping_Check (p) != 0; } bool isNumeric () const { return PyNumber_Check (p) != 0; } bool isSequence () const { return PySequence_Check (p) != 0; } bool isTrue () const { return PyObject_IsTrue (p) != 0; } bool isType (const Type& t) const; bool isTuple() const { return Py::_Tuple_Check(p); } bool isString() const { return Py::_String_Check(p) || Py::_Unicode_Check(p); } bool isUnicode() const { return Py::_Unicode_Check( p ); } bool isBoolean() const { return Py::_Boolean_Check( p ); } // Commands void setAttr (const std::string& s, const Object& value) { if(PyObject_SetAttrString (p, const_cast(s.c_str()), *value) == -1) throw AttributeError ("getAttr failed."); } void delAttr (const std::string& s) { if(PyObject_DelAttrString (p, const_cast(s.c_str())) == -1) throw AttributeError ("delAttr failed."); } // PyObject_SetItem is too weird to be using from C++ // so it is intentionally omitted. void delItem (const Object& key) { //if(PyObject_DelItem(p, *key) == -1) // failed to link on Windows? throw KeyError("delItem failed."); } // Equality and comparison use PyObject_RichCompareBool bool operator==(const Object& o2) const { int k = PyObject_RichCompareBool (p, *o2, Py_EQ); if (PyErr_Occurred()) throw Exception(); return k != 0; } bool operator!=(const Object& o2) const { int k = PyObject_RichCompareBool (p, *o2, Py_NE); if (PyErr_Occurred()) throw Exception(); return k != 0; } bool operator>=(const Object& o2) const { int k = PyObject_RichCompareBool (p, *o2, Py_GE); if (PyErr_Occurred()) throw Exception(); return k != 0; } bool operator<=(const Object& o2) const { int k = PyObject_RichCompareBool (p, *o2, Py_LE); if (PyErr_Occurred()) throw Exception(); return k != 0; } bool operator<(const Object& o2) const { int k = PyObject_RichCompareBool (p, *o2, Py_LT); if (PyErr_Occurred()) throw Exception(); return k != 0; } bool operator>(const Object& o2) const { int k = PyObject_RichCompareBool (p, *o2, Py_GT); if (PyErr_Occurred()) throw Exception(); return k != 0; } }; // End of class Object inline PyObject* new_reference_to(const Object& g) { PyObject* p = g.ptr(); Py::_XINCREF(p); return p; } // Nothing() is what an extension method returns if // there is no other return value. inline Object Nothing() { return Object(Py::_None()); } // Python special None value inline Object None() { return Object(Py::_None()); } // Python special Boolean values inline Object False() { return Object(Py::_False()); } inline Object True() { return Object(Py::_True()); } // TMM: 31May'01 - Added the #ifndef so I can exlude iostreams. #ifndef CXX_NO_IOSTREAMS std::ostream& operator<< (std::ostream& os, const Object& ob); #endif // Class Type class Type: public Object { public: explicit Type (PyObject* pyob, bool owned = false): Object(pyob, owned) { validate(); } Type (const Object& ob): Object(*ob) { validate(); } Type(const Type& t): Object(t) { validate(); } Type& operator= (const Object& rhs) { return (*this = *rhs); } Type& operator= (PyObject* rhsp) { if(ptr() == rhsp) return *this; set (rhsp); return *this; } virtual bool accepts (PyObject *pyob) const { return pyob && Py::_Type_Check (pyob); } }; // // Convert an owned Python pointer into a CXX Object // inline Object asObject (PyObject *p) { return Object(p, true); } // =============================================== // class boolean class Boolean: public Object { public: // Constructor Boolean (PyObject *pyob, bool owned = false) : Object (pyob, owned) { validate(); } Boolean (const Boolean& ob): Object(*ob) { validate(); } // create from bool Boolean (bool v=false) { set(PyBool_FromLong(v ? 1 : 0), true); validate(); } explicit Boolean (const Object& ob) : Object( *ob ) { validate(); } // Assignment increases reference count on pointer Boolean& operator= (const Object& rhs) { return (*this = *rhs); } Boolean& operator= (PyObject* rhsp) { if(ptr() == rhsp) return *this; set (rhsp); return *this; } // Membership virtual bool accepts (PyObject *pyob) const { return pyob && PyObject_IsTrue(pyob) != -1; } // convert to long operator bool() const { return PyObject_IsTrue (ptr()) != 0; } Boolean& operator= (bool v) { set (PyBool_FromLong (v ? 1 : 0), true); return *this; } }; // =============================================== // class Int class Int: public Object { public: // Constructor Int (PyObject *pyob, bool owned = false): Object (pyob, owned) { validate(); } Int (const Int& ob): Object(*ob) { validate(); } // create from long Int (long v = 0L): Object(PyInt_FromLong(v), true) { validate(); } // create from int Int (int v) { long w = v; set(PyInt_FromLong(w), true); validate(); } // create from bool Int (bool v) { long w = v ? 1 : 0; set(PyInt_FromLong(w), true); validate(); } explicit Int (const Object& ob) { set(PyNumber_Int(*ob), true); validate(); } // Assignment acquires new ownership of pointer Int& operator= (const Object& rhs) { return (*this = *rhs); } Int& operator= (PyObject* rhsp) { if(ptr() == rhsp) return *this; set (PyNumber_Int(rhsp), true); return *this; } // Membership virtual bool accepts (PyObject *pyob) const { return pyob && Py::_Int_Check (pyob); } // convert to long operator long() const { return PyInt_AsLong (ptr()); } #ifdef HAVE_LONG_LONG // convert to long long PY_LONG_LONG asLongLong() const { return PyLong_AsLongLong (ptr()); } // convert to unsigned long long unsigned PY_LONG_LONG asUnsignedLongLong() const { return PyLong_AsUnsignedLongLong (ptr()); } #endif // assign from an int Int& operator= (int v) { set (PyInt_FromLong (long(v)), true); return *this; } // assign from long Int& operator= (long v) { set (PyInt_FromLong (v), true); return *this; } #ifdef HAVE_LONG_LONG // assign from long long Int& operator= (PY_LONG_LONG v) { set (PyLong_FromLongLong (v), true); return *this; } // assign from unsigned long long Int& operator= (unsigned PY_LONG_LONG v) { set (PyLong_FromUnsignedLongLong (v), true); return *this; } #endif }; // =============================================== // class Long class Long: public Object { public: // Constructor explicit Long (PyObject *pyob, bool owned = false): Object (pyob, owned) { validate(); } Long (const Long& ob): Object(ob.ptr()) { validate(); } // create from long explicit Long (long v = 0L) : Object(PyLong_FromLong(v), true) { validate(); } // create from unsigned long explicit Long (unsigned long v) : Object(PyLong_FromUnsignedLong(v), true) { validate(); } // create from int explicit Long (int v) : Object(PyLong_FromLong(static_cast(v)), true) { validate(); } // try to create from any object Long (const Object& ob) : Object(PyNumber_Long(*ob), true) { validate(); } // Assignment acquires new ownership of pointer Long& operator= (const Object& rhs) { return (*this = *rhs); } Long& operator= (PyObject* rhsp) { if(ptr() == rhsp) return *this; set (PyNumber_Long(rhsp), true); return *this; } // Membership virtual bool accepts (PyObject *pyob) const { return pyob && Py::_Long_Check (pyob); } // convert to long long as_long() const { return PyLong_AsLong( ptr() ); } // convert to long operator long() const { return as_long(); } // convert to unsigned operator unsigned long() const { return PyLong_AsUnsignedLong (ptr()); } operator double() const { return PyLong_AsDouble (ptr()); } // assign from an int Long& operator= (int v) { set(PyLong_FromLong (long(v)), true); return *this; } // assign from long Long& operator= (long v) { set(PyLong_FromLong (v), true); return *this; } // assign from unsigned long Long& operator= (unsigned long v) { set(PyLong_FromUnsignedLong (v), true); return *this; } }; #ifdef HAVE_LONG_LONG // =============================================== // class LongLong class LongLong: public Object { public: // Constructor explicit LongLong (PyObject *pyob, bool owned = false): Object (pyob, owned) { validate(); } LongLong (const LongLong& ob): Object(ob.ptr()) { validate(); } // create from long long explicit LongLong (PY_LONG_LONG v = 0L) : Object(PyLong_FromLongLong(v), true) { validate(); } // create from unsigned long long explicit LongLong (unsigned PY_LONG_LONG v) : Object(PyLong_FromUnsignedLongLong(v), true) { validate(); } // create from long explicit LongLong (long v) : Object(PyLong_FromLongLong(v), true) { validate(); } // create from unsigned long explicit LongLong (unsigned long v) : Object(PyLong_FromUnsignedLongLong(v), true) { validate(); } // create from int explicit LongLong (int v) : Object(PyLong_FromLongLong(static_cast(v)), true) { validate(); } // try to create from any object LongLong (const Object& ob) : Object(PyNumber_Long(*ob), true) { validate(); } // Assignment acquires new ownership of pointer LongLong& operator= (const Object& rhs) { return (*this = *rhs); } LongLong& operator= (PyObject* rhsp) { if(ptr() == rhsp) return *this; set (PyNumber_Long(rhsp), true); return *this; } // Membership virtual bool accepts (PyObject *pyob) const { return pyob && Py::_Long_Check (pyob); } // convert to long long operator PY_LONG_LONG() const { return PyLong_AsLongLong (ptr()); } // convert to unsigned long operator unsigned PY_LONG_LONG() const { return PyLong_AsUnsignedLongLong (ptr()); } // convert to long operator long() const { return PyLong_AsLong (ptr()); } // convert to unsigned operator unsigned long() const { return PyLong_AsUnsignedLong (ptr()); } operator double() const { return PyLong_AsDouble (ptr()); } // assign from an int LongLong& operator= (int v) { set(PyLong_FromLongLong (long(v)), true); return *this; } // assign from long long LongLong& operator= (PY_LONG_LONG v) { set(PyLong_FromLongLong (v), true); return *this; } // assign from unsigned long long LongLong& operator= (unsigned PY_LONG_LONG v) { set(PyLong_FromUnsignedLongLong (v), true); return *this; } // assign from long LongLong& operator= (long v) { set(PyLong_FromLongLong (v), true); return *this; } // assign from unsigned long LongLong& operator= (unsigned long v) { set(PyLong_FromUnsignedLongLong (v), true); return *this; } }; #endif // =============================================== // class Float // class Float: public Object { public: // Constructor explicit Float (PyObject *pyob, bool owned = false): Object(pyob, owned) { validate(); } Float (const Float& f): Object(f) { validate(); } // make from double explicit Float (double v=0.0) : Object(PyFloat_FromDouble (v), true) { validate(); } // try to make from any object Float (const Object& ob) : Object(PyNumber_Float(*ob), true) { validate(); } Float& operator= (const Object& rhs) { return (*this = *rhs); } Float& operator= (PyObject* rhsp) { if(ptr() == rhsp) return *this; set (PyNumber_Float(rhsp), true); return *this; } // Membership virtual bool accepts (PyObject *pyob) const { return pyob && Py::_Float_Check (pyob); } // convert to double operator double () const { return PyFloat_AsDouble (ptr()); } // assign from a double Float& operator= (double v) { set(PyFloat_FromDouble (v), true); return *this; } // assign from an int Float& operator= (int v) { set(PyFloat_FromDouble (double(v)), true); return *this; } // assign from long Float& operator= (long v) { set(PyFloat_FromDouble (double(v)), true); return *this; } // assign from an Int Float& operator= (const Int& iob) { set(PyFloat_FromDouble (double(long(iob))), true); return *this; } }; // =============================================== // class Complex class Complex: public Object { public: // Constructor explicit Complex (PyObject *pyob, bool owned = false): Object(pyob, owned) { validate(); } Complex (const Complex& f): Object(f) { validate(); } // make from double explicit Complex (double v=0.0, double w=0.0) :Object(PyComplex_FromDoubles (v, w), true) { validate(); } Complex& operator= (const Object& rhs) { return (*this = *rhs); } Complex& operator= (PyObject* rhsp) { if(ptr() == rhsp) return *this; set (rhsp); return *this; } // Membership virtual bool accepts (PyObject *pyob) const { return pyob && Py::_Complex_Check (pyob); } // convert to Py_complex operator Py_complex () const { return PyComplex_AsCComplex (ptr()); } // assign from a Py_complex Complex& operator= (const Py_complex& v) { set(PyComplex_FromCComplex (v), true); return *this; } // assign from a double Complex& operator= (double v) { set(PyComplex_FromDoubles (v, 0.0), true); return *this; } // assign from an int Complex& operator= (int v) { set(PyComplex_FromDoubles (double(v), 0.0), true); return *this; } // assign from long Complex& operator= (long v) { set(PyComplex_FromDoubles (double(v), 0.0), true); return *this; } // assign from an Int Complex& operator= (const Int& iob) { set(PyComplex_FromDoubles (double(long(iob)), 0.0), true); return *this; } double real() const { return PyComplex_RealAsDouble(ptr()); } double imag() const { return PyComplex_ImagAsDouble(ptr()); } }; // Sequences // Sequences are here represented as sequences of items of type T. // The base class SeqBase represents that. // In basic Python T is always "Object". // seqref is what you get if you get elements from a non-const SeqBase. // Note: seqref could probably be a nested class in SeqBase but that might stress // some compilers needlessly. Simlarly for mapref later. // While this class is not intended for enduser use, it needs some public // constructors for the benefit of the STL. // See Scott Meyer's More Essential C++ for a description of proxies. // This application is even more complicated. We are doing an unusual thing // in having a double proxy. If we want the STL to work // properly we have to compromise by storing the rvalue inside. The // entire Object API is repeated so that things like s[i].isList() will // work properly. // Still, once in a while a weird compiler message may occur using expressions like x[i] // Changing them to Object(x[i]) helps the compiler to understand that the // conversion of a seqref to an Object is wanted. template class seqref { protected: SeqBase& s; // the sequence int offset; // item number T the_item; // lvalue public: seqref (SeqBase& seq, sequence_index_type j) : s(seq), offset(j), the_item (s.getItem(j)) {} seqref (const seqref& range) : s(range.s), offset(range.offset), the_item(range.the_item) {} // TMM: added this seqref ctor for use with STL algorithms seqref (Object& obj) : s(dynamic_cast< SeqBase&>(obj)) , offset( NULL ) , the_item(s.getItem(offset)) {} ~seqref() {} operator T() const { // rvalue return the_item; } seqref& operator=(const seqref& rhs) { //used as lvalue the_item = rhs.the_item; s.setItem(offset, the_item); return *this; } seqref& operator=(const T& ob) { // used as lvalue the_item = ob; s.setItem(offset, ob); return *this; } // forward everything else to the item PyObject* ptr () const { return the_item.ptr(); } int reference_count () const { // the reference count return the_item.reference_count(); } Type type () const { return the_item.type(); } String str () const; String repr () const; bool hasAttr (const std::string& attr_name) const { return the_item.hasAttr(attr_name); } Object getAttr (const std::string& attr_name) const { return the_item.getAttr(attr_name); } Object getItem (const Object& key) const { return the_item.getItem(key); } long hashValue () const { return the_item.hashValue(); } bool isCallable () const { return the_item.isCallable(); } bool isInstance () const { return the_item.isInstance(); } bool isDict () const { return the_item.isDict(); } bool isList () const { return the_item.isList(); } bool isMapping () const { return the_item.isMapping(); } bool isNumeric () const { return the_item.isNumeric(); } bool isSequence () const { return the_item.isSequence(); } bool isTrue () const { return the_item.isTrue(); } bool isType (const Type& t) const { return the_item.isType (t); } bool isTuple() const { return the_item.isTuple(); } bool isString() const { return the_item.isString(); } // Commands void setAttr (const std::string& attr_name, const Object& value) { the_item.setAttr(attr_name, value); } void delAttr (const std::string& attr_name) { the_item.delAttr(attr_name); } void delItem (const Object& key) { the_item.delItem(key); } bool operator==(const Object& o2) const { return the_item == o2; } bool operator!=(const Object& o2) const { return the_item != o2; } bool operator>=(const Object& o2) const { return the_item >= o2; } bool operator<=(const Object& o2) const { return the_item <= o2; } bool operator<(const Object& o2) const { return the_item < o2; } bool operator>(const Object& o2) const { return the_item > o2; } }; // end of seqref // class SeqBase // ...the base class for all sequence types template class SeqBase: public Object { public: // STL definitions typedef size_t size_type; typedef seqref reference; typedef T const_reference; typedef seqref* pointer; typedef int difference_type; typedef T value_type; // TMM: 26Jun'01 virtual size_type max_size() const { return std::string::npos; // ? } virtual size_type capacity() const { return size(); } virtual void swap(SeqBase& c) { SeqBase temp = c; c = ptr(); set(temp.ptr()); } virtual size_type size () const { return PySequence_Length (ptr()); } explicit SeqBase () :Object(PyTuple_New(0), true) { validate(); } explicit SeqBase (PyObject* pyob, bool owned=false) : Object(pyob, owned) { validate(); } SeqBase (const Object& ob): Object(ob) { validate(); } // Assignment acquires new ownership of pointer SeqBase& operator= (const Object& rhs) { return (*this = *rhs); } SeqBase& operator= (PyObject* rhsp) { if(ptr() == rhsp) return *this; set (rhsp); return *this; } virtual bool accepts (PyObject *pyob) const { return pyob && PySequence_Check (pyob); } size_type length () const { return PySequence_Length (ptr()); } // Element access const T operator[](sequence_index_type index) const { return getItem(index); } seqref operator[](sequence_index_type index) { return seqref(*this, index); } virtual T getItem (sequence_index_type i) const { return T(asObject(PySequence_GetItem (ptr(), i))); } virtual void setItem (sequence_index_type i, const T& ob) { if (PySequence_SetItem (ptr(), i, *ob) == -1) { throw Exception(); } } SeqBase repeat (int count) const { return SeqBase (PySequence_Repeat (ptr(), count), true); } SeqBase concat (const SeqBase& other) const { return SeqBase (PySequence_Concat(ptr(), *other), true); } // more STL compatability const T front () const { return getItem(0); } seqref front() { return seqref(*this, 0); } const T back() const { return getItem(size()-1); } seqref back() { return seqref(*this, size()-1); } void verify_length(size_type required_size) const { if (size() != required_size) throw IndexError ("Unexpected SeqBase length."); } void verify_length(size_type min_size, size_type max_size) const { size_type n = size(); if (n < min_size || n > max_size) throw IndexError ("Unexpected SeqBase length."); } class iterator : public random_access_iterator_parent(seqref) { protected: friend class SeqBase; SeqBase* seq; int count; public: ~iterator () {} iterator () : seq( 0 ) , count( 0 ) {} iterator (SeqBase* s, int where) : seq( s ) , count( where ) {} iterator (const iterator& other) : seq( other.seq ) , count( other.count ) {} bool eql (const iterator& other) const { return (seq->ptr() == other.seq->ptr()) && (count == other.count); } bool neq (const iterator& other) const { return (seq->ptr() != other.seq->ptr()) || (count != other.count); } bool lss (const iterator& other) const { return (count < other.count); } bool gtr (const iterator& other) const { return (count > other.count); } bool leq (const iterator& other) const { return (count <= other.count); } bool geq (const iterator& other) const { return (count >= other.count); } seqref operator*() { return seqref(*seq, count); } seqref operator[] (sequence_index_type i) { return seqref(*seq, count + i); } iterator& operator=(const iterator& other) { if (this == &other) return *this; seq = other.seq; count = other.count; return *this; } iterator operator+(int n) const { return iterator(seq, count + n); } iterator operator-(int n) const { return iterator(seq, count - n); } iterator& operator+=(int n) { count = count + n; return *this; } iterator& operator-=(int n) { count = count - n; return *this; } int operator-(const iterator& other) const { if (*seq != *other.seq) throw RuntimeError ("SeqBase::iterator comparison error"); return count - other.count; } // prefix ++ iterator& operator++ () { count++; return *this;} // postfix ++ iterator operator++ (int) { return iterator(seq, count++);} // prefix -- iterator& operator-- () { count--; return *this;} // postfix -- iterator operator-- (int) { return iterator(seq, count--);} std::string diagnose() const { std::OSTRSTREAM oss; oss << "iterator diagnosis " << seq << ", " << count << std::ends; return std::string(oss.str()); } }; // end of class SeqBase::iterator iterator begin () { return iterator(this, 0); } iterator end () { return iterator(this, length()); } class const_iterator : public random_access_iterator_parent(const Object) { protected: friend class SeqBase; const SeqBase* seq; sequence_index_type count; private: const_iterator (const SeqBase* s, int where) : seq( s ) , count( where ) {} public: ~const_iterator () {} const_iterator () : seq( 0 ) , count( 0 ) {} const_iterator(const const_iterator& other) : seq( other.seq ) , count( other.count ) {} const T operator*() const { return seq->getItem(count); } const T operator[] (sequence_index_type i) const { return seq->getItem(count + i); } const_iterator& operator=(const const_iterator& other) { if (this == &other) return *this; seq = other.seq; count = other.count; return *this; } const_iterator operator+(int n) const { return const_iterator(seq, count + n); } bool eql (const const_iterator& other) const { return (seq->ptr() == other.seq->ptr()) && (count == other.count); } bool neq (const const_iterator& other) const { return (seq->ptr() != other.seq->ptr()) || (count != other.count); } bool lss (const const_iterator& other) const { return (count < other.count); } bool gtr (const const_iterator& other) const { return (count > other.count); } bool leq (const const_iterator& other) const { return (count <= other.count); } bool geq (const const_iterator& other) const { return (count >= other.count); } const_iterator operator-(int n) { return const_iterator(seq, count - n); } const_iterator& operator+=(int n) { count = count + n; return *this; } const_iterator& operator-=(int n) { count = count - n; return *this; } int operator-(const const_iterator& other) const { if (*seq != *other.seq) throw RuntimeError ("SeqBase::const_iterator::- error"); return count - other.count; } // prefix ++ const_iterator& operator++ () { count++; return *this;} // postfix ++ const_iterator operator++ (int) { return const_iterator(seq, count++);} // prefix -- const_iterator& operator-- () { count--; return *this;} // postfix -- const_iterator operator-- (int) { return const_iterator(seq, count--);} }; // end of class SeqBase::const_iterator const_iterator begin () const { return const_iterator(this, 0); } const_iterator end () const { return const_iterator(this, length()); } }; // Here's an important typedef you might miss if reading too fast... typedef SeqBase Sequence; template bool operator==(const EXPLICIT_TYPENAME SeqBase::iterator& left, const EXPLICIT_TYPENAME SeqBase::iterator& right); template bool operator!=(const EXPLICIT_TYPENAME SeqBase::iterator& left, const EXPLICIT_TYPENAME SeqBase::iterator& right); template bool operator< (const EXPLICIT_TYPENAME SeqBase::iterator& left, const EXPLICIT_TYPENAME SeqBase::iterator& right); template bool operator> (const EXPLICIT_TYPENAME SeqBase::iterator& left, const EXPLICIT_TYPENAME SeqBase::iterator& right); template bool operator<=(const EXPLICIT_TYPENAME SeqBase::iterator& left, const EXPLICIT_TYPENAME SeqBase::iterator& right); template bool operator>=(const EXPLICIT_TYPENAME SeqBase::iterator& left, const EXPLICIT_TYPENAME SeqBase::iterator& right); template bool operator==(const EXPLICIT_TYPENAME SeqBase::const_iterator& left, const EXPLICIT_TYPENAME SeqBase::const_iterator& right); template bool operator!=(const EXPLICIT_TYPENAME SeqBase::const_iterator& left, const EXPLICIT_TYPENAME SeqBase::const_iterator& right); template bool operator< (const EXPLICIT_TYPENAME SeqBase::const_iterator& left, const EXPLICIT_TYPENAME SeqBase::const_iterator& right); template bool operator> (const EXPLICIT_TYPENAME SeqBase::const_iterator& left, const EXPLICIT_TYPENAME SeqBase::const_iterator& right); template bool operator<=(const EXPLICIT_TYPENAME SeqBase::const_iterator& left, const EXPLICIT_TYPENAME SeqBase::const_iterator& right); template bool operator>=(const EXPLICIT_TYPENAME SeqBase::const_iterator& left, const EXPLICIT_TYPENAME SeqBase::const_iterator& right); extern bool operator==(const Sequence::iterator& left, const Sequence::iterator& right); extern bool operator!=(const Sequence::iterator& left, const Sequence::iterator& right); extern bool operator< (const Sequence::iterator& left, const Sequence::iterator& right); extern bool operator> (const Sequence::iterator& left, const Sequence::iterator& right); extern bool operator<=(const Sequence::iterator& left, const Sequence::iterator& right); extern bool operator>=(const Sequence::iterator& left, const Sequence::iterator& right); extern bool operator==(const Sequence::const_iterator& left, const Sequence::const_iterator& right); extern bool operator!=(const Sequence::const_iterator& left, const Sequence::const_iterator& right); extern bool operator< (const Sequence::const_iterator& left, const Sequence::const_iterator& right); extern bool operator> (const Sequence::const_iterator& left, const Sequence::const_iterator& right); extern bool operator<=(const Sequence::const_iterator& left, const Sequence::const_iterator& right); extern bool operator>=(const Sequence::const_iterator& left, const Sequence::const_iterator& right); // ================================================== // class Char // Python strings return strings as individual elements. // I'll try having a class Char which is a String of length 1 // typedef std::basic_string unicodestring; extern Py_UNICODE unicode_null_string[1]; class Char: public Object { public: explicit Char (PyObject *pyob, bool owned = false): Object(pyob, owned) { validate(); } Char (const Object& ob): Object(ob) { validate(); } Char (const std::string& v = "") :Object(PyString_FromStringAndSize (const_cast(v.c_str()),1), true) { validate(); } Char (char v) : Object(PyString_FromStringAndSize (&v, 1), true) { validate(); } Char (Py_UNICODE v) : Object(PyUnicode_FromUnicode (&v, 1), true) { validate(); } // Assignment acquires new ownership of pointer Char& operator= (const Object& rhs) { return (*this = *rhs); } Char& operator= (PyObject* rhsp) { if(ptr() == rhsp) return *this; set (rhsp); return *this; } // Membership virtual bool accepts (PyObject *pyob) const { return pyob && (Py::_String_Check(pyob) || Py::_Unicode_Check(pyob)) && PySequence_Length (pyob) == 1; } // Assignment from C string Char& operator= (const std::string& v) { set(PyString_FromStringAndSize (const_cast(v.c_str()),1), true); return *this; } Char& operator= (char v) { set(PyString_FromStringAndSize (&v, 1), true); return *this; } Char& operator= (const unicodestring& v) { set(PyUnicode_FromUnicode (const_cast(v.data()),1), true); return *this; } Char& operator= (Py_UNICODE v) { set(PyUnicode_FromUnicode (&v, 1), true); return *this; } // Conversion operator String() const; operator std::string () const { return std::string(PyString_AsString (ptr())); } }; #ifdef PYCXX_PYTHON_2TO3 // String and Bytes compatible with Python3 version in 6.0.0 PyCXX class Bytes; class String: public SeqBase { public: virtual size_type capacity() const { return max_size(); } explicit String( PyObject *pyob, bool owned = false) : SeqBase( pyob, owned ) { validate(); } String( const Object& ob): SeqBase(ob) { validate(); } String() : SeqBase( PyString_FromStringAndSize( "", 0 ), true ) { validate(); } String( const std::string& v ) : SeqBase( PyString_FromStringAndSize( const_cast(v.data()), static_cast( v.length() ) ), true ) { validate(); } String( const Py_UNICODE *s, int length ) : SeqBase( PyUnicode_FromUnicode( s, length ), true ) { validate(); } String( const char *s, const char *encoding, const char *error="strict" ) : SeqBase( PyUnicode_Decode( s, strlen( s ), encoding, error ), true ) { validate(); } String( const char *s, int len, const char *encoding, const char *error="strict" ) : SeqBase( PyUnicode_Decode( s, len, encoding, error ), true ) { validate(); } String( const std::string &s, const char *encoding, const char *error="strict" ) : SeqBase( PyUnicode_Decode( s.c_str(), s.length(), encoding, error ), true ) { validate(); } String( const char *v, int vsize ) : SeqBase(PyString_FromStringAndSize( const_cast(v), vsize ), true ) { validate(); } String( const char *v ) : SeqBase( PyString_FromString( v ), true ) { validate(); } // Assignment acquires new ownership of pointer String &operator=( const Object &rhs ) { return *this = *rhs; } String& operator= (PyObject *rhsp) { if( ptr() == rhsp ) return *this; set (rhsp); return *this; } // Membership virtual bool accepts (PyObject *pyob) const { return pyob && (Py::_String_Check(pyob) || Py::_Unicode_Check(pyob)); } // Assignment from C string String& operator=( const std::string &v ) { set( PyString_FromStringAndSize( const_cast( v.data() ), static_cast( v.length() ) ), true ); return *this; } String& operator=( const unicodestring &v ) { set( PyUnicode_FromUnicode( const_cast( v.data() ), static_cast( v.length() ) ), true ); return *this; } // Encode Bytes encode( const char *encoding, const char *error="strict" ) const; // Queries virtual size_type size() const { if( isUnicode() ) { return static_cast( PyUnicode_GET_SIZE (ptr()) ); } else { return static_cast( PyString_Size (ptr()) ); } } operator std::string() const { return as_std_string( "utf-8" ); } std::string as_std_string( const char *encoding, const char *error="strict" ) const; unicodestring as_unicodestring() const { if( isUnicode() ) { return unicodestring( PyUnicode_AS_UNICODE( ptr() ), static_cast( PyUnicode_GET_SIZE( ptr() ) ) ); } else { throw TypeError("can only return unicodestring from Unicode object"); } } const Py_UNICODE *unicode_data() const { if( isUnicode() ) { return PyUnicode_AS_UNICODE( ptr() ); } else { throw TypeError("can only return unicode_data from Unicode object"); } } }; class Bytes: public SeqBase { public: virtual size_type capacity() const { return max_size(); } explicit Bytes (PyObject *pyob, bool owned = false): SeqBase(pyob, owned) { validate(); } Bytes (const Object& ob): SeqBase(ob) { validate(); } Bytes() : SeqBase( PyString_FromStringAndSize( "", 0 ), true ) { validate(); } Bytes( const std::string& v ) : SeqBase( PyString_FromStringAndSize( const_cast(v.data()), static_cast( v.length() ) ), true ) { validate(); } Bytes( const char *v, int vsize ) : SeqBase(PyString_FromStringAndSize( const_cast(v), vsize ), true ) { validate(); } Bytes( const char *v ) : SeqBase( PyString_FromString( v ), true ) { validate(); } // Assignment acquires new ownership of pointer Bytes &operator= ( const Object& rhs ) { return *this = *rhs; } Bytes &operator= (PyObject *rhsp) { if( ptr() == rhsp ) return *this; set (rhsp); return *this; } // Membership virtual bool accepts( PyObject *pyob ) const { return pyob && (Py::_String_Check( pyob ) || Py::_Unicode_Check( pyob )); } // Assignment from C string Bytes &operator= (const std::string& v) { set( PyString_FromStringAndSize( const_cast( v.data() ), static_cast( v.length() ) ), true ); return *this; } Bytes &operator= (const unicodestring& v) { set( PyUnicode_FromUnicode( const_cast( v.data() ), static_cast( v.length() ) ), true ); return *this; } String decode( const char *encoding, const char *error="strict" ) { return Object( PyString_AsDecodedObject( ptr(), encoding, error ), true ); } // Queries virtual size_type size () const { if( isUnicode() ) { return static_cast( PyUnicode_GET_SIZE (ptr()) ); } else { return static_cast( PyString_Size (ptr()) ); } } operator std::string () const { return as_std_string(); } std::string as_std_string() const { if( isUnicode() ) { throw TypeError("cannot return std::string from Unicode object"); } else { return std::string( PyString_AsString( ptr() ), static_cast( PyString_Size( ptr() ) ) ); } } unicodestring as_unicodestring() const { if( isUnicode() ) { return unicodestring( PyUnicode_AS_UNICODE( ptr() ), static_cast( PyUnicode_GET_SIZE( ptr() ) ) ); } else { throw TypeError("can only return unicodestring from Unicode object"); } } }; #else // original PyCXX 5.4.x version of String class String: public SeqBase { public: virtual size_type capacity() const { return max_size(); } explicit String (PyObject *pyob, bool owned = false): SeqBase(pyob, owned) { validate(); } String (const Object& ob): SeqBase(ob) { validate(); } String() : SeqBase( PyString_FromStringAndSize( "", 0 ), true ) { validate(); } String( const std::string& v ) : SeqBase( PyString_FromStringAndSize( const_cast(v.data()), static_cast( v.length() ) ), true ) { validate(); } String( const char *s, const char *encoding, const char *error="strict" ) : SeqBase( PyUnicode_Decode( s, strlen( s ), encoding, error ), true ) { validate(); } String( const char *s, int len, const char *encoding, const char *error="strict" ) : SeqBase( PyUnicode_Decode( s, len, encoding, error ), true ) { validate(); } String( const std::string &s, const char *encoding, const char *error="strict" ) : SeqBase( PyUnicode_Decode( s.c_str(), s.length(), encoding, error ), true ) { validate(); } String( const char *v, int vsize ) : SeqBase(PyString_FromStringAndSize( const_cast(v), vsize ), true ) { validate(); } String( const char* v ) : SeqBase( PyString_FromString( v ), true ) { validate(); } // Assignment acquires new ownership of pointer String& operator= ( const Object& rhs ) { return *this = *rhs; } String& operator= (PyObject* rhsp) { if( ptr() == rhsp ) return *this; set (rhsp); return *this; } // Membership virtual bool accepts (PyObject *pyob) const { return pyob && (Py::_String_Check(pyob) || Py::_Unicode_Check(pyob)); } // Assignment from C string String& operator= (const std::string& v) { set( PyString_FromStringAndSize( const_cast( v.data() ), static_cast( v.length() ) ), true ); return *this; } String& operator= (const unicodestring& v) { set( PyUnicode_FromUnicode( const_cast( v.data() ), static_cast( v.length() ) ), true ); return *this; } // Encode String encode( const char *encoding, const char *error="strict" ) const { if( isUnicode() ) { return String( PyUnicode_AsEncodedString( ptr(), encoding, error ), true ); } else { return String( PyString_AsEncodedObject( ptr(), encoding, error ), true ); } } String decode( const char *encoding, const char *error="strict" ) { return Object( PyString_AsDecodedObject( ptr(), encoding, error ), true ); } // Queries virtual size_type size () const { if( isUnicode() ) { return static_cast( PyUnicode_GET_SIZE (ptr()) ); } else { return static_cast( PyString_Size (ptr()) ); } } operator std::string () const { return as_std_string(); } std::string as_std_string() const { if( isUnicode() ) { throw TypeError("cannot return std::string from Unicode object"); } else { return std::string( PyString_AsString( ptr() ), static_cast( PyString_Size( ptr() ) ) ); } } std::string as_std_string( const char *encoding, const char *error="strict" ) const; unicodestring as_unicodestring() const { if( isUnicode() ) { return unicodestring( PyUnicode_AS_UNICODE( ptr() ), static_cast( PyUnicode_GET_SIZE( ptr() ) ) ); } else { throw TypeError("can only return unicodestring from Unicode object"); } } }; #endif // ================================================== // class Tuple class Tuple: public Sequence { public: virtual void setItem (sequence_index_type offset, const Object&ob) { // note PyTuple_SetItem is a thief... if(PyTuple_SetItem (ptr(), offset, new_reference_to(ob)) == -1) { throw Exception(); } } // Constructor explicit Tuple (PyObject *pyob, bool owned = false): Sequence (pyob, owned) { validate(); } Tuple (const Object& ob): Sequence(ob) { validate(); } // New tuple of a given size explicit Tuple (int size = 0) { set(PyTuple_New (size), true); validate (); for (sequence_index_type i=0; i < size; i++) { if(PyTuple_SetItem (ptr(), i, new_reference_to(Py::_None())) == -1) { throw Exception(); } } } // Tuple from any sequence explicit Tuple (const Sequence& s) { sequence_index_type limit( sequence_index_type( s.length() ) ); set(PyTuple_New (limit), true); validate(); for(sequence_index_type i=0; i < limit; i++) { if(PyTuple_SetItem (ptr(), i, new_reference_to(s[i])) == -1) { throw Exception(); } } } // Assignment acquires new ownership of pointer Tuple& operator= (const Object& rhs) { return (*this = *rhs); } Tuple& operator= (PyObject* rhsp) { if(ptr() == rhsp) return *this; set (rhsp); return *this; } // Membership virtual bool accepts (PyObject *pyob) const { return pyob && Py::_Tuple_Check (pyob); } Tuple getSlice (int i, int j) const { return Tuple (PySequence_GetSlice (ptr(), i, j), true); } }; class TupleN: public Tuple { public: TupleN() : Tuple( 0 ) { } TupleN( const Object &obj1 ) : Tuple( 1 ) { setItem( 0, obj1 ); } TupleN( const Object &obj1, const Object &obj2 ) : Tuple( 2 ) { setItem( 0, obj1 ); setItem( 1, obj2 ); } TupleN( const Object &obj1, const Object &obj2, const Object &obj3 ) : Tuple( 3 ) { setItem( 0, obj1 ); setItem( 1, obj2 ); setItem( 2, obj3 ); } TupleN( const Object &obj1, const Object &obj2, const Object &obj3, const Object &obj4 ) : Tuple( 4 ) { setItem( 0, obj1 ); setItem( 1, obj2 ); setItem( 2, obj3 ); setItem( 3, obj4 ); } TupleN( const Object &obj1, const Object &obj2, const Object &obj3, const Object &obj4, const Object &obj5 ) : Tuple( 5 ) { setItem( 0, obj1 ); setItem( 1, obj2 ); setItem( 2, obj3 ); setItem( 3, obj4 ); setItem( 4, obj5 ); } TupleN( const Object &obj1, const Object &obj2, const Object &obj3, const Object &obj4, const Object &obj5, const Object &obj6 ) : Tuple( 6 ) { setItem( 0, obj1 ); setItem( 1, obj2 ); setItem( 2, obj3 ); setItem( 3, obj4 ); setItem( 4, obj5 ); setItem( 5, obj6 ); } TupleN( const Object &obj1, const Object &obj2, const Object &obj3, const Object &obj4, const Object &obj5, const Object &obj6, const Object &obj7 ) : Tuple( 7 ) { setItem( 0, obj1 ); setItem( 1, obj2 ); setItem( 2, obj3 ); setItem( 3, obj4 ); setItem( 4, obj5 ); setItem( 5, obj6 ); setItem( 6, obj7 ); } TupleN( const Object &obj1, const Object &obj2, const Object &obj3, const Object &obj4, const Object &obj5, const Object &obj6, const Object &obj7, const Object &obj8 ) : Tuple( 8 ) { setItem( 0, obj1 ); setItem( 1, obj2 ); setItem( 2, obj3 ); setItem( 3, obj4 ); setItem( 4, obj5 ); setItem( 5, obj6 ); setItem( 6, obj7 ); setItem( 7, obj8 ); } TupleN( const Object &obj1, const Object &obj2, const Object &obj3, const Object &obj4, const Object &obj5, const Object &obj6, const Object &obj7, const Object &obj8, const Object &obj9 ) : Tuple( 9 ) { setItem( 0, obj1 ); setItem( 1, obj2 ); setItem( 2, obj3 ); setItem( 3, obj4 ); setItem( 4, obj5 ); setItem( 5, obj6 ); setItem( 6, obj7 ); setItem( 7, obj8 ); setItem( 8, obj9 ); } virtual ~TupleN() { } }; // ================================================== // class List class List: public Sequence { public: // Constructor explicit List (PyObject *pyob, bool owned = false): Sequence(pyob, owned) { validate(); } List (const Object& ob): Sequence(ob) { validate(); } // Creation at a fixed size List (int size = 0) { set(PyList_New (size), true); validate(); for (sequence_index_type i=0; i < size; i++) { if(PyList_SetItem (ptr(), i, new_reference_to(Py::_None())) == -1) { throw Exception(); } } } // List from a sequence List (const Sequence& s): Sequence() { int n = (int)s.length(); set(PyList_New (n), true); validate(); for (sequence_index_type i=0; i < n; i++) { if(PyList_SetItem (ptr(), i, new_reference_to(s[i])) == -1) { throw Exception(); } } } virtual size_type capacity() const { return max_size(); } // Assignment acquires new ownership of pointer List& operator= (const Object& rhs) { return (*this = *rhs); } List& operator= (PyObject* rhsp) { if(ptr() == rhsp) return *this; set (rhsp); return *this; } // Membership virtual bool accepts (PyObject *pyob) const { return pyob && Py::_List_Check (pyob); } List getSlice (int i, int j) const { return List (PyList_GetSlice (ptr(), i, j), true); } void setSlice (int i, int j, const Object& v) { if(PyList_SetSlice (ptr(), i, j, *v) == -1) { throw Exception(); } } void append (const Object& ob) { if(PyList_Append (ptr(), *ob) == -1) { throw Exception(); } } void insert (int i, const Object& ob) { if(PyList_Insert (ptr(), i, *ob) == -1) { throw Exception(); } } void sort () { if(PyList_Sort(ptr()) == -1) { throw Exception(); } } void reverse () { if(PyList_Reverse(ptr()) == -1) { throw Exception(); } } }; // Mappings // ================================================== template class mapref { protected: MapBase& s; // the map Object key; // item key T the_item; public: mapref (MapBase& map, const std::string& k) : s(map), the_item() { key = String(k); if(map.hasKey(key)) the_item = map.getItem(key); } mapref (MapBase& map, const Object& k) : s(map), key(k), the_item() { if(map.hasKey(key)) the_item = map.getItem(key); } virtual ~mapref() {} // MapBase stuff // lvalue mapref& operator=(const mapref& other) { if(this == &other) return *this; the_item = other.the_item; s.setItem(key, other.the_item); return *this; } mapref& operator= (const T& ob) { the_item = ob; s.setItem (key, ob); return *this; } // rvalue operator T() const { return the_item; } // forward everything else to the_item PyObject* ptr () const { return the_item.ptr(); } int reference_count () const { // the mapref count return the_item.reference_count(); } Type type () const { return the_item.type(); } String str () const { return the_item.str(); } String repr () const { return the_item.repr(); } bool hasAttr (const std::string& attr_name) const { return the_item.hasAttr(attr_name); } Object getAttr (const std::string& attr_name) const { return the_item.getAttr(attr_name); } Object getItem (const Object& k) const { return the_item.getItem(k); } long hashValue () const { return the_item.hashValue(); } bool isCallable () const { return the_item.isCallable(); } bool isInstance () const { return the_item.isInstance(); } bool isList () const { return the_item.isList(); } bool isMapping () const { return the_item.isMapping(); } bool isNumeric () const { return the_item.isNumeric(); } bool isSequence () const { return the_item.isSequence(); } bool isTrue () const { return the_item.isTrue(); } bool isType (const Type& t) const { return the_item.isType (t); } bool isTuple() const { return the_item.isTuple(); } bool isString() const { return the_item.isString(); } // Commands void setAttr (const std::string& attr_name, const Object& value) { the_item.setAttr(attr_name, value); } void delAttr (const std::string& attr_name) { the_item.delAttr(attr_name); } void delItem (const Object& k) { the_item.delItem(k); } }; // end of mapref // TMM: now for mapref template< class T > bool operator==(const mapref& left, const mapref& right) { return true; // NOT completed. } template< class T > bool operator!=(const mapref& left, const mapref& right) { return true; // not completed. } template class MapBase: public Object { protected: explicit MapBase() {} public: // reference: proxy class for implementing [] // TMM: 26Jun'01 - the types // If you assume that Python mapping is a hash_map... // hash_map::value_type is not assignable, but // (*it).second = data must be a valid expression typedef size_t size_type; typedef Object key_type; typedef mapref data_type; typedef std::pair< const T, T > value_type; typedef std::pair< const T, mapref > reference; typedef const std::pair< const T, const T > const_reference; typedef std::pair< const T, mapref > pointer; // Constructor explicit MapBase (PyObject *pyob, bool owned = false): Object(pyob, owned) { validate(); } // TMM: 02Jul'01 - changed MapBase to Object in next line MapBase (const Object& ob): Object(ob) { validate(); } // Assignment acquires new ownership of pointer MapBase& operator= (const Object& rhs) { return (*this = *rhs); } MapBase& operator= (PyObject* rhsp) { if(ptr() == rhsp) return *this; set (rhsp); return *this; } // Membership virtual bool accepts (PyObject *pyob) const { return pyob && PyMapping_Check(pyob); } // Clear -- PyMapping Clear is missing // void clear () { List k = keys(); for(List::iterator i = k.begin(); i != k.end(); i++) { delItem(*i); } } virtual size_type size() const { return PyMapping_Length (ptr()); } // Element Access T operator[](const std::string& key) const { return getItem(key); } T operator[](const Object& key) const { return getItem(key); } mapref operator[](const std::string& key) { return mapref(*this, key); } mapref operator[](const Object& key) { return mapref(*this, key); } int length () const { return PyMapping_Length (ptr()); } bool hasKey (const std::string& s) const { return PyMapping_HasKeyString (ptr(),const_cast(s.c_str())) != 0; } bool hasKey (const Object& s) const { return PyMapping_HasKey (ptr(), s.ptr()) != 0; } T getItem (const std::string& s) const { return T( asObject(PyMapping_GetItemString (ptr(),const_cast(s.c_str()))) ); } T getItem (const Object& s) const { return T( asObject(PyObject_GetItem (ptr(), s.ptr())) ); } virtual void setItem (const char *s, const Object& ob) { if (PyMapping_SetItemString (ptr(), const_cast(s), *ob) == -1) { throw Exception(); } } virtual void setItem (const std::string& s, const Object& ob) { if (PyMapping_SetItemString (ptr(), const_cast(s.c_str()), *ob) == -1) { throw Exception(); } } virtual void setItem (const Object& s, const Object& ob) { if (PyObject_SetItem (ptr(), s.ptr(), ob.ptr()) == -1) { throw Exception(); } } void delItem (const std::string& s) { if (PyMapping_DelItemString (ptr(), const_cast(s.c_str())) == -1) { throw Exception(); } } void delItem (const Object& s) { if (PyMapping_DelItem (ptr(), *s) == -1) { throw Exception(); } } // Queries List keys () const { return List(PyMapping_Keys(ptr()), true); } List values () const { // each returned item is a (key, value) pair return List(PyMapping_Values(ptr()), true); } List items () const { return List(PyMapping_Items(ptr()), true); } class iterator { // : public forward_iterator_parent( std::pair ) { protected: typedef std::forward_iterator_tag iterator_category; typedef std::pair< const T, T > value_type; typedef int difference_type; typedef std::pair< const T, mapref > pointer; typedef std::pair< const T, mapref > reference; friend class MapBase; // MapBase* map; List keys; // for iterating over the map int pos; // index into the keys private: iterator( MapBase* m, List k, int p ) : map( m ) , keys( k ) , pos( p ) {} public: ~iterator () {} iterator () : map( 0 ) , keys() , pos() {} iterator (MapBase* m, bool end = false ) : map( m ) , keys( m->keys() ) , pos( end ? keys.length() : 0 ) {} iterator (const iterator& other) : map( other.map ) , keys( other.keys ) , pos( other.pos ) {} reference operator*() { Object key = keys[ pos ]; return std::make_pair(key, mapref(*map,key)); } iterator& operator=(const iterator& other) { if (this == &other) return *this; map = other.map; keys = other.keys; pos = other.pos; return *this; } bool eql(const iterator& right) const { return map->ptr() == right.map->ptr() && pos == right.pos; } bool neq( const iterator& right ) const { return map->ptr() != right.map->ptr() || pos != right.pos; } // pointer operator->() { // return ; // } // prefix ++ iterator& operator++ () { pos++; return *this;} // postfix ++ iterator operator++ (int) { return iterator(map, keys, pos++);} // prefix -- iterator& operator-- () { pos--; return *this;} // postfix -- iterator operator-- (int) { return iterator(map, keys, pos--);} std::string diagnose() const { std::OSTRSTREAM oss; oss << "iterator diagnosis " << map << ", " << pos << std::ends; return std::string(oss.str()); } }; // end of class MapBase::iterator iterator begin () { return iterator(this); } iterator end () { return iterator(this, true); } class const_iterator { protected: typedef std::forward_iterator_tag iterator_category; typedef const std::pair< const T, T > value_type; typedef int difference_type; typedef const std::pair< const T, T > pointer; typedef const std::pair< const T, T > reference; friend class MapBase; const MapBase* map; List keys; // for iterating over the map int pos; // index into the keys private: const_iterator( const MapBase* m, List k, int p ) : map( m ) , keys( k ) , pos( p ) {} public: ~const_iterator () {} const_iterator () : map( 0 ) , keys() , pos() {} const_iterator (const MapBase* m, bool end = false ) : map( m ) , keys( m->keys() ) , pos( end ? keys.length() : 0 ) {} const_iterator(const const_iterator& other) : map( other.map ) , keys( other.keys ) , pos( other.pos ) {} bool eql(const const_iterator& right) const { return map->ptr() == right.map->ptr() && pos == right.pos; } bool neq( const const_iterator& right ) const { return map->ptr() != right.map->ptr() || pos != right.pos; } const_reference operator*() { Object key = keys[ pos ]; return std::make_pair( key, mapref( *map, key ) ); } const_iterator& operator=(const const_iterator& other) { if (this == &other) return *this; map = other.map; keys = other.keys; pos = other.pos; return *this; } // prefix ++ const_iterator& operator++ () { pos++; return *this;} // postfix ++ const_iterator operator++ (int) { return const_iterator(map, keys, pos++);} // prefix -- const_iterator& operator-- () { pos--; return *this;} // postfix -- const_iterator operator-- (int) { return const_iterator(map, keys, pos--);} }; // end of class MapBase::const_iterator const_iterator begin () const { return const_iterator(this); } const_iterator end () const { return const_iterator(this, true); } }; // end of MapBase typedef MapBase Mapping; template bool operator==(const EXPLICIT_TYPENAME MapBase::iterator& left, const EXPLICIT_TYPENAME MapBase::iterator& right); template bool operator!=(const EXPLICIT_TYPENAME MapBase::iterator& left, const EXPLICIT_TYPENAME MapBase::iterator& right); template bool operator==(const EXPLICIT_TYPENAME MapBase::const_iterator& left, const EXPLICIT_TYPENAME MapBase::const_iterator& right); template bool operator!=(const EXPLICIT_TYPENAME MapBase::const_iterator& left, const EXPLICIT_TYPENAME MapBase::const_iterator& right); extern bool operator==(const Mapping::iterator& left, const Mapping::iterator& right); extern bool operator!=(const Mapping::iterator& left, const Mapping::iterator& right); extern bool operator==(const Mapping::const_iterator& left, const Mapping::const_iterator& right); extern bool operator!=(const Mapping::const_iterator& left, const Mapping::const_iterator& right); // ================================================== // class Dict class Dict: public Mapping { public: // Constructor explicit Dict (PyObject *pyob, bool owned=false): Mapping (pyob, owned) { validate(); } Dict (const Object& ob): Mapping(ob) { validate(); } // Creation Dict () { set(PyDict_New (), true); validate(); } // Assignment acquires new ownership of pointer Dict& operator= (const Object& rhs) { return (*this = *rhs); } Dict& operator= (PyObject* rhsp) { if(ptr() == rhsp) return *this; set(rhsp); return *this; } // Membership virtual bool accepts (PyObject *pyob) const { return pyob && Py::_Dict_Check (pyob); } }; class Callable: public Object { public: // Constructor explicit Callable (): Object() {} explicit Callable (PyObject *pyob, bool owned = false): Object (pyob, owned) { validate(); } Callable (const Object& ob): Object(ob) { validate(); } // Assignment acquires new ownership of pointer Callable& operator= (const Object& rhs) { return (*this = *rhs); } Callable& operator= (PyObject* rhsp) { if(ptr() == rhsp) return *this; set (rhsp); return *this; } // Membership virtual bool accepts (PyObject *pyob) const { return pyob && PyCallable_Check (pyob); } // Call Object apply(const Tuple& args) const { return asObject(PyObject_CallObject(ptr(), args.ptr())); } // Call with keywords Object apply(const Tuple& args, const Dict& kw) const { return asObject( PyEval_CallObjectWithKeywords( ptr(), args.ptr(), kw.ptr() ) ); } Object apply(PyObject* pargs = 0) const { return apply (Tuple(pargs)); } }; class Module: public Object { public: explicit Module (PyObject* pyob, bool owned = false): Object (pyob, owned) { validate(); } // Construct from module name explicit Module (const std::string&s): Object() { PyObject *m = PyImport_AddModule( const_cast(s.c_str()) ); set( m, false ); validate (); } // Copy constructor acquires new ownership of pointer Module (const Module& ob): Object(*ob) { validate(); } Module& operator= (const Object& rhs) { return (*this = *rhs); } Module& operator= (PyObject* rhsp) { if(ptr() == rhsp) return *this; set(rhsp); return *this; } Dict getDict() { return Dict(PyModule_GetDict(ptr())); // Caution -- PyModule_GetDict returns borrowed reference! } }; // Call function helper inline Object Object::callMemberFunction( const std::string &function_name ) const { Callable target( getAttr( function_name ) ); Tuple args( 0 ); return target.apply( args ); } inline Object Object::callMemberFunction( const std::string &function_name, const Tuple &args ) const { Callable target( getAttr( function_name ) ); return target.apply( args ); } inline Object Object::callMemberFunction( const std::string &function_name, const Tuple &args, const Dict &kw ) const { Callable target( getAttr( function_name ) ); return target.apply( args, kw ); } // Numeric interface inline Object operator+ (const Object& a) { return asObject(PyNumber_Positive(*a)); } inline Object operator- (const Object& a) { return asObject(PyNumber_Negative(*a)); } inline Object abs(const Object& a) { return asObject(PyNumber_Absolute(*a)); } inline std::pair coerce(const Object& a, const Object& b) { PyObject *p1, *p2; p1 = *a; p2 = *b; if(PyNumber_Coerce(&p1,&p2) == -1) { throw Exception(); } return std::pair(asObject(p1), asObject(p2)); } inline Object operator+ (const Object& a, const Object& b) { return asObject(PyNumber_Add(*a, *b)); } inline Object operator+ (const Object& a, int j) { return asObject(PyNumber_Add(*a, *Int(j))); } inline Object operator+ (const Object& a, double v) { return asObject(PyNumber_Add(*a, *Float(v))); } inline Object operator+ (int j, const Object& b) { return asObject(PyNumber_Add(*Int(j), *b)); } inline Object operator+ (double v, const Object& b) { return asObject(PyNumber_Add(*Float(v), *b)); } inline Object operator- (const Object& a, const Object& b) { return asObject(PyNumber_Subtract(*a, *b)); } inline Object operator- (const Object& a, int j) { return asObject(PyNumber_Subtract(*a, *Int(j))); } inline Object operator- (const Object& a, double v) { return asObject(PyNumber_Subtract(*a, *Float(v))); } inline Object operator- (int j, const Object& b) { return asObject(PyNumber_Subtract(*Int(j), *b)); } inline Object operator- (double v, const Object& b) { return asObject(PyNumber_Subtract(*Float(v), *b)); } inline Object operator* (const Object& a, const Object& b) { return asObject(PyNumber_Multiply(*a, *b)); } inline Object operator* (const Object& a, int j) { return asObject(PyNumber_Multiply(*a, *Int(j))); } inline Object operator* (const Object& a, double v) { return asObject(PyNumber_Multiply(*a, *Float(v))); } inline Object operator* (int j, const Object& b) { return asObject(PyNumber_Multiply(*Int(j), *b)); } inline Object operator* (double v, const Object& b) { return asObject(PyNumber_Multiply(*Float(v), *b)); } inline Object operator/ (const Object& a, const Object& b) { return asObject(PyNumber_Divide(*a, *b)); } inline Object operator/ (const Object& a, int j) { return asObject(PyNumber_Divide(*a, *Int(j))); } inline Object operator/ (const Object& a, double v) { return asObject(PyNumber_Divide(*a, *Float(v))); } inline Object operator/ (int j, const Object& b) { return asObject(PyNumber_Divide(*Int(j), *b)); } inline Object operator/ (double v, const Object& b) { return asObject(PyNumber_Divide(*Float(v), *b)); } inline Object operator% (const Object& a, const Object& b) { return asObject(PyNumber_Remainder(*a, *b)); } inline Object operator% (const Object& a, int j) { return asObject(PyNumber_Remainder(*a, *Int(j))); } inline Object operator% (const Object& a, double v) { return asObject(PyNumber_Remainder(*a, *Float(v))); } inline Object operator% (int j, const Object& b) { return asObject(PyNumber_Remainder(*Int(j), *b)); } inline Object operator% (double v, const Object& b) { return asObject(PyNumber_Remainder(*Float(v), *b)); } inline Object type(const Exception&) // return the type of the error { PyObject *ptype, *pvalue, *ptrace; PyErr_Fetch(&ptype, &pvalue, &ptrace); Object result; if(ptype) result = ptype; PyErr_Restore(ptype, pvalue, ptrace); return result; } inline Object value(const Exception&) // return the value of the error { PyObject *ptype, *pvalue, *ptrace; PyErr_Fetch(&ptype, &pvalue, &ptrace); Object result; if(pvalue) result = pvalue; PyErr_Restore(ptype, pvalue, ptrace); return result; } inline Object trace(const Exception&) // return the traceback of the error { PyObject *ptype, *pvalue, *ptrace; PyErr_Fetch(&ptype, &pvalue, &ptrace); Object result; if(ptrace) result = ptrace; PyErr_Restore(ptype, pvalue, ptrace); return result; } template String seqref::str () const { return the_item.str(); } template String seqref::repr () const { return the_item.repr(); } } // namespace Py #endif // __CXX_Objects__h pycxx-6.2.5/CXX/Python2/PythonType.hxx000644 000771 000000 00000011075 11722441226 020037 0ustar00barrywheel000000 000000 //----------------------------------------------------------------------------- // // Copyright (c) 1998 - 2007, The Regents of the University of California // Produced at the Lawrence Livermore National Laboratory // All rights reserved. // // This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The // full copyright notice is contained in the file COPYRIGHT located at the root // of the PyCXX distribution. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // - Redistributions of source code must retain the above copyright notice, // this list of conditions and the disclaimer below. // - Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the disclaimer (as noted below) in the // documentation and/or materials provided with the distribution. // - Neither the name of the UC/LLNL nor the names of its contributors may be // used to endorse or promote products derived from this software without // specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF // CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH // DAMAGE. // //----------------------------------------------------------------------------- #ifndef __CXX_PythonType__h #define __CXX_PythonType__h namespace Py { class PythonType { public: // if you define one sequence method you must define // all of them except the assigns PythonType( size_t base_size, int itemsize, const char *default_name ); virtual ~PythonType(); const char *getName() const; const char *getDoc() const; PyTypeObject *type_object() const; PythonType &name( const char *nam ); PythonType &doc( const char *d ); PythonType &supportClass( void ); PythonType &dealloc( void (*f)( PyObject* ) ); #if defined( PYCXX_PYTHON_2TO3 ) PythonType &supportPrint( void ); #endif PythonType &supportGetattr( void ); PythonType &supportSetattr( void ); PythonType &supportGetattro( void ); PythonType &supportSetattro( void ); #if defined( PYCXX_PYTHON_2TO3 ) PythonType &supportCompare( void ); #endif PythonType &supportRichCompare( void ); PythonType &supportRepr( void ); PythonType &supportStr( void ); PythonType &supportHash( void ); PythonType &supportCall( void ); PythonType &supportIter( void ); PythonType &supportSequenceType( void ); PythonType &supportMappingType( void ); PythonType &supportNumberType( void ); PythonType &supportBufferType( void ); PythonType &set_tp_dealloc( void (*tp_dealloc)( PyObject * ) ); PythonType &set_tp_init( int (*tp_init)( PyObject *self, PyObject *args, PyObject *kwds ) ); PythonType &set_tp_new( PyObject *(*tp_new)( PyTypeObject *subtype, PyObject *args, PyObject *kwds ) ); PythonType &set_methods( PyMethodDef *methods ); // call once all support functions have been called to ready the type bool readyType(); protected: void init_sequence(); void init_mapping(); void init_number(); void init_buffer(); PyTypeObject *table; PySequenceMethods *sequence_table; PyMappingMethods *mapping_table; PyNumberMethods *number_table; PyBufferProcs *buffer_table; private: // // prevent the compiler generating these unwanted functions // PythonType( const PythonType &tb ); // unimplemented void operator=( const PythonType &t ); // unimplemented }; } // Namespace Py // End of __CXX_PythonType__h #endif