changeset 35:5073ff11e2b6 lp-trunk

Support for implicit conversion of dictionaries and lists. Modified build configuration.
author David Grundberg <individ@acc.umu.se>
date Tue, 05 May 2009 21:11:40 +0200
parents 84be5ee8cc44 (current diff) 24e1734d26b0 (diff)
children 25f49207de46
files INSTALL m4/ax_python.m4 testfile.m
diffstat 21 files changed, 1290 insertions(+), 644 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Mon Nov 17 12:19:57 2008 +0100
+++ b/ChangeLog	Tue May 05 21:11:40 2009 +0200
@@ -1,3 +1,19 @@
+2009-05-05  David Grundberg  <individ@acc.umu.se>
+
+	* python_to_octave.cc: Function pydict_to_octmap modified.
+	* m4/ax_octave.m4, m4/ax_python_devel.m4: New files.
+	* m4/ax_python.m4: Removed.
+	* m4/ax_boost_python.m4, README, INSTALL: Rewritten.
+	* configure.ac, setup.py.in, Jamfile.in, Makefile.am: Adjusted to
+	new Autoconf macros.
+
+2008-11-17  Håkan Fors Nilsson  <c04hfn@cs.umu.se>
+
+	* octave_to_python.cc: Added functions octcell_to_pyobject and 
+	octmap_to_pyobject.
+	* python_to_octave.cc: Added functions pydict_to_octmap and 
+	pylist_to_cellarray.
+
 2008-11-17  David Grundberg  <individ@acc.umu.se>
 
 	* pytave.cc: func_eval: Improved pytave.OctaveError messages, now
@@ -30,3 +46,8 @@
 
 	First launchpad.net check in.
 
+Local Variables:
+coding: utf-8
+fill-column: 74
+End:
+vim: set textwidth=74 noexpandtab :
--- a/INSTALL	Mon Nov 17 12:19:57 2008 +0100
+++ b/INSTALL	Tue May 05 21:11:40 2009 +0200
@@ -1,237 +1,154 @@
-Installation Instructions
-*************************
-
-Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005 Free
-Software Foundation, Inc.
-
-This file is free documentation; the Free Software Foundation gives
-unlimited permission to copy, distribute and modify it.
-
-Basic Installation
-==================
-
-These are generic installation instructions. See README for pytave
-instructions.
-
-   The `configure' shell script attempts to guess correct values for
-various system-dependent variables used during compilation.  It uses
-those values to create a `Makefile' in each directory of the package.
-It may also create one or more `.h' files containing system-dependent
-definitions.  Finally, it creates a shell script `config.status' that
-you can run in the future to recreate the current configuration, and a
-file `config.log' containing compiler output (useful mainly for
-debugging `configure').
-
-   It can also use an optional file (typically called `config.cache'
-and enabled with `--cache-file=config.cache' or simply `-C') that saves
-the results of its tests to speed up reconfiguring.  (Caching is
-disabled by default to prevent problems with accidental use of stale
-cache files.)
-
-   If you need to do unusual things to compile the package, please try
-to figure out how `configure' could check whether to do them, and mail
-diffs or instructions to the address given in the `README' so they can
-be considered for the next release.  If you are using the cache, and at
-some point `config.cache' contains results you don't want to keep, you
-may remove or edit it.
-
-   The file `configure.ac' (or `configure.in') is used to create
-`configure' by a program called `autoconf'.  You only need
-`configure.ac' if you want to change it or regenerate `configure' using
-a newer version of `autoconf'.
-
-The simplest way to compile this package is:
-
-  1. `cd' to the directory containing the package's source code and type
-     `./configure' to configure the package for your system.  If you're
-     using `csh' on an old version of System V, you might need to type
-     `sh ./configure' instead to prevent `csh' from trying to execute
-     `configure' itself.
-
-     Running `configure' takes awhile.  While running, it prints some
-     messages telling which features it is checking for.
-
-  2. Type `make' to compile the package.
-
-  3. Optionally, type `make check' to run any self-tests that come with
-     the package.
-
-  4. Type `make install' to install the programs and any data files and
-     documentation.
-
-  5. You can remove the program binaries and object files from the
-     source code directory by typing `make clean'.  To also remove the
-     files that `configure' created (so you can compile the package for
-     a different kind of computer), type `make distclean'.  There is
-     also a `make maintainer-clean' target, but that is intended mainly
-     for the package's developers.  If you use it, you may have to get
-     all sorts of other programs in order to regenerate files that came
-     with the distribution.
-
-Compilers and Options
+Building instructions
 =====================
 
-Some systems require unusual options for compilation or linking that the
-`configure' script does not know about.  Run `./configure --help' for
-details on some of the pertinent environment variables.
+You can use either Python distutils, GNU Automake or Boost BJam to
+build pytave. The configure script outputs files for all these build
+systems. Autoconf's VPATH is supported on all build systems.
+
+    Use the configure script to set up Octave and Boost::Python
+paths. Run `./configure --help' for more info.
+
+Dependencies
+============
+
+Configuring:
+	an sh shell capable of running `configure'
 
-   You can give `configure' initial values for configuration parameters
-by setting variables in the command line or in the environment.  Here
-is an example:
+Building:
+	Python's distutils or
+	make or
+	BJam
+
+Linked and tested with:
+    Python 2.4
+    Boost::Python 1.33
+    Octave 3.0.2
 
-     ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix
+Bootstraping from Bazaar trunk
+==============================
+
+  1. `bzr branch lp:pytave'
 
-   *Note Defining Variables::, for more details.
+  2. `autoreconf --install'
 
-Compiling For Multiple Architectures
-====================================
+  3. `./configure'
+
+Autotools
+=========
 
-You can compile the package for more than one kind of computer at the
-same time, by placing the object files for each architecture in their
-own directory.  To do this, you must use a version of `make' that
-supports the `VPATH' variable, such as GNU `make'.  `cd' to the
-directory where you want the object files and executables to go and run
-the `configure' script.  `configure' automatically checks for the
-source code in the directory that `configure' is in and in `..'.
+The Autotools build system need not be installed to build the
+module. You need `make' and all library dependencies though.
+
+  1. Create the `Makefile' by typing:
+	 `./configure --prefix=/directory/where/you/want/the/module/file'
+
+  2. Type `make' to build the extention module.
+
+  3. To copy the pytave dynamic library to the prefix, type
+     `make install'
+
+BJam
+====
+
+BJam must be installed in order to build the module. You also need a
+proper `user-config.jam' file in your home directory.
 
-   If you have to use a `make' that does not support the `VPATH'
-variable, you have to compile the package for one architecture at a
-time in the source code directory.  After you have installed the
-package for one architecture, use `make distclean' before reconfiguring
-for another architecture.
+  1. Create `Jamfile' and `project-root.jam' by typing `./configure'
+
+  2. Use your `bjam' command to build the extention module. 
+
+user-config.jam
+===============
 
-Installation Names
-==================
+For your convenience, here the content of a typical ~/user-config.jam
+on a GNU/Linux system:
+
+using gcc ;
+using python : 2.5 ;
+
+Distutils
+=========
+
+  1. Create the `setup.py' file by typing `./configure'
 
-By default, `make install' installs the package's commands under
-`/usr/local/bin', include files under `/usr/local/include', etc.  You
-can specify an installation prefix other than `/usr/local' by giving
-`configure' the option `--prefix=PREFIX'.
+  2. Run `python setup.py build' to build and package the extention
+     module together with the pure Python files.
+
+Running from build directory
+============================
+
+Pytave is made up of three parts. The `pytave' package, the
+`pytave/pytave' module and the `pytave/_pytave' extention. When the
+user uses `import pytave', the pytave package __init__ script loads
+both the module and the extention. It is important that they both can
+be found. 
 
-   You can specify separate installation prefixes for
-architecture-specific files and architecture-independent files.  If you
-pass the option `--exec-prefix=PREFIX' to `configure', the package uses
-PREFIX as the prefix for installing programs and libraries.
-Documentation and other data files still use the regular prefix.
+  1. Follow the Distutils build instructions. A complete Python
+     package directory called `pytave' is created in
+     `build/lib.something'
+
+  2. Start the Python interactive interpreter with
+     `PYTHONPATH=build/lib.linux-i686-2.4/ python' (with appropriate
+     changes for your system.)
 
-   In addition, if you use an unusual directory layout you can give
-options like `--bindir=DIR' to specify different values for particular
-kinds of files.  Run `configure --help' for a list of the directories
-you can set and what kinds of files go in them.
+  3. In the interpreter you can now access Octave through Python:
+
+import pytave
+import Numeric
+pytave.feval(1, "cos", 0)
+b = pytave.addpath(".")
+pytave.feval(1, "testfile", 42)
+
+     (Observe that there is no testfile.m file in the distribution.
+     You could create one for yourself.)
 
-   If the package supports it, you can cause programs to be installed
-with an extra prefix or suffix on their names by giving `configure' the
-option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+    Using BJam or Automake instead of Distutils, you load the
+`pytave/pytave' module and the extention instead of the whole
+package. Using `import pytave' now calls the module directly, but the
+difference is transparent to the user.
 
-Optional Features
-=================
+    Basically all you want to do is load Python with shared library
+for the pytave extention (called `pytave/_pytave') and the native
+`pytave/pytave' module. BJam creates shared library in the
+`bin/something/something' directory, while Autotools hide a working
+shared library in the `.libs' directory. The contents of the `pytave'
+package is stored in the directory `package' of the source
+package. This is an example for an Autotools build.
+
+  1. Follow the Autotools build instructions.
+
+  2. Start the Python interpreter with a Python path set to a path
+     containing `_pytave.so' and the `package' directory. A common way
+     to do this with the bash shell is to execute this command:
+     `PYTHONPATH=.libs:package python'.
 
-Some packages pay attention to `--enable-FEATURE' options to
-`configure', where FEATURE indicates an optional part of the package.
-They may also pay attention to `--with-PACKAGE' options, where PACKAGE
-is something like `gnu-as' or `x' (for the X Window System).  The
-`README' should mention any `--enable-' and `--with-' options that the
-package recognizes.
+     With BJam that command would be something like:
+     `PYTHONPATH=bin/something/something:package python'.
+
+Running test suite in build directory
+=====================================
+
+Read the instructions above, and start the script test/test.py.
 
-   For packages that use the X Window System, `configure' can usually
-find the X include and library files automatically, but if it doesn't,
-you can use the `configure' options `--x-includes=DIR' and
-`--x-libraries=DIR' to specify their locations.
+Installing with distutils
+=========================
+
+  1. Run `python setup.py install'
 
-Specifying the System Type
+Creating a source dist
+======================
+
+  1. Run `make distcheck'
+
+Hint about foreign systems
 ==========================
 
-There may be some features `configure' cannot figure out automatically,
-but needs to determine by the type of machine the package will run on.
-Usually, assuming the package is built to be run on the _same_
-architectures, `configure' can figure that out, but if it prints a
-message saying it cannot guess the machine type, give it the
-`--build=TYPE' option.  TYPE can either be a short name for the system
-type, such as `sun4', or a canonical name which has the form:
-
-     CPU-COMPANY-SYSTEM
-
-where SYSTEM can have one of these forms:
-
-     OS KERNEL-OS
-
-   See the file `config.sub' for the possible values of each field.  If
-`config.sub' isn't included in this package, then this package doesn't
-need to know the machine type.
-
-   If you are _building_ compiler tools for cross-compiling, you should
-use the option `--target=TYPE' to select the type of system they will
-produce code for.
-
-   If you want to _use_ a cross compiler, that generates code for a
-platform different from the build platform, you should specify the
-"host" platform (i.e., that on which the generated programs will
-eventually be run) with `--host=TYPE'.
-
-Sharing Defaults
-================
-
-If you want to set default values for `configure' scripts to share, you
-can create a site shell script called `config.site' that gives default
-values for variables like `CC', `cache_file', and `prefix'.
-`configure' looks for `PREFIX/share/config.site' if it exists, then
-`PREFIX/etc/config.site' if it exists.  Or, you can set the
-`CONFIG_SITE' environment variable to the location of the site script.
-A warning: not all `configure' scripts look for a site script.
-
-Defining Variables
-==================
-
-Variables not defined in a site shell script can be set in the
-environment passed to `configure'.  However, some packages may run
-configure again during the build, and the customized values of these
-variables may be lost.  In order to avoid this problem, you should set
-them in the `configure' command line, using `VAR=value'.  For example:
+If you are running on a system incapable of executing the configure
+scripts (e.g. a Microsoft Windows system), you may want to try
+installing the `MinGW' and `MSYS' packages, and build everything
+inside that environment.  This isn't for the faint of hearted though,
+since you need/want to build Octave too.  It is probably easier than
+trying to build without configure scripts, that's all.  There are no
+guarentees that it will build at all, it has not been tested.
 
-     ./configure CC=/usr/local2/bin/gcc
-
-causes the specified `gcc' to be used as the C compiler (unless it is
-overridden in the site shell script).  Here is a another example:
-
-     /bin/bash ./configure CONFIG_SHELL=/bin/bash
-
-Here the `CONFIG_SHELL=/bin/bash' operand causes subsequent
-configuration-related scripts to be executed by `/bin/bash'.
-
-`configure' Invocation
-======================
-
-`configure' recognizes the following options to control how it operates.
-
-`--help'
-`-h'
-     Print a summary of the options to `configure', and exit.
-
-`--version'
-`-V'
-     Print the version of Autoconf used to generate the `configure'
-     script, and exit.
-
-`--cache-file=FILE'
-     Enable the cache: use and save the results of the tests in FILE,
-     traditionally `config.cache'.  FILE defaults to `/dev/null' to
-     disable caching.
-
-`--config-cache'
-`-C'
-     Alias for `--cache-file=config.cache'.
-
-`--quiet'
-`--silent'
-`-q'
-     Do not print messages saying which checks are being made.  To
-     suppress all normal output, redirect it to `/dev/null' (any error
-     messages will still be shown).
-
-`--srcdir=DIR'
-     Look for the package's source code in directory DIR.  Usually
-     `configure' can determine that directory automatically.
-
-`configure' also accepts some other, not widely useful, options.  Run
-`configure --help' for more details.
-
+EOF.
\ No newline at end of file
--- a/Jamfile.in	Mon Nov 17 12:19:57 2008 +0100
+++ b/Jamfile.in	Tue May 05 21:11:40 2009 +0200
@@ -6,8 +6,8 @@
 	<library>@JAM_LIBOCTAVE@
 	<library>@JAM_LIBCRUFT@
 	<library>@JAM_LIBOCTINTERP@
-	<include>@PYTHON_INCLUDE_DIR@
-	<include>@PYTAVE_OCTAVE_INCLUDE_PATH@
+#	<include>@PYTHON_INCLUDE_DIR@
+	<include>@OCTAVE_INCLUDEDIR@
 	<include>@abs_srcdir@
 	<include>@abs_builddir@
 	<define>"HAVE_CONFIG_H"
--- a/Makefile.am	Mon Nov 17 12:19:57 2008 +0100
+++ b/Makefile.am	Tue May 05 21:11:40 2009 +0200
@@ -4,11 +4,11 @@
 package/__init__.py package/pytave.py
 EXTRA_libdir = @PYTAVE_MODULE_INSTALL_PATH@
 
-_pytave_la_CPPFLAGS = -I@PYTAVE_OCTAVE_INCLUDE_PATH@ -I@PYTHON_INCLUDE_DIR@
+_pytave_la_CPPFLAGS = @OCTAVE_CPPFLAGS@ @PYTHON_CPPFLAGS@
 
 # Having -module in LDFLAGS lets us use a non-standard library name 
 # (e.g. _pytave instead of libpytave)
-_pytave_la_LDFLAGS = -module -L@PYTAVE_OCTAVE_RPATH@ -loctinterp -loctave  \
+_pytave_la_LDFLAGS = -module -L@OCTAVE_LIBRARYDIR@ -loctinterp -loctave  \
 -lcruft -l@BOOST_PYTHON_LIB@ -R @PYTAVE_OCTAVE_RPATH@
 
 _pytave_la_SOURCES = octave_to_python.cc pytave.cc python_to_octave.cc \
--- a/NEWS	Mon Nov 17 12:19:57 2008 +0100
+++ b/NEWS	Tue May 05 21:11:40 2009 +0200
@@ -0,0 +1,8 @@
+Version 0.1-bzr 
+
+* Added functionality for one-row cell arrays.  The Python list is
+  converted to a one-row cell array and vice versa.
+
+* Added functionality for structs.  The Python distionary is converted
+  to a Octave struct and vice versa.  The implementation tries to be
+  as true as possible to Octave's struct constructor.
--- a/README	Mon Nov 17 12:19:57 2008 +0100
+++ b/README	Tue May 05 21:11:40 2009 +0200
@@ -1,150 +1,196 @@
-pytave README
-*************
+-*- coding:utf-8 -*-
 
-Building instructions
-=====================
+Pytave README
+
+For installation instructions specific for Pytave, please see the
+INSTALL file.
 
-You can use either Python distutils, GNU Automake or Boost BJam to
-build pytave. The configure script outputs files for all these build
-systems. Autoconf's VPATH is supported on all build systems.
+Contents of this document
+=========================
 
-    Use the configure script to set up Octave and Boost::Python
-paths. Run `./configure --help' for more info. There are two custom
-arguments that control building of pytave, `--with-octave' and
-`--with-boost-python'.
+1. What is Pytave?
+2. Gotchas
+3. Pytave and multi-threading
+4. Python/Octave cheat sheet
 
-Dependencies
-============
+What is Pytave?
+***************
 
-Configuring:
-	an sh shell capable of running `configure'
+Pytave enables Python scripts to use existing m-files (Octave/Matlab
+scripts) for numerical calculations.  The Octave language interpreter
+is embedded as a module to Python.
 
-Building:
-	Python's distutils or
-	make or
-	BJam
+Example use
+===========
+
+Calling Octave code in the interactive Python interpreter:
 
-Linked and tested with:
-    Python 2.4
-    Boost::Python 1.33
-    Octave 3.0.2
+>>> import pytave
+>>> pytave.feval(1, "cos", 0)
+(1.0,)
+
+Goals
+=====
 
-Bootstraping from Bazaar trunk
-==============================
+Pytave strives to uphold these points
 
-  1. `bzr branch lp:pytave'
+  * Good out of the box experience
 
-  2. `autoreconf --install'
-
-  3. `./configure'
+  * Good-natured implicit type conversions, no strange PyApple ->
+    octave_orange -> PyBanana chains
 
-Autotools
-=========
+Features
+========
 
-The Autotools build system need not be installed to build the
-module. You need `make' and all library dependencies though.
+A short list of what Pytave is capable of
 
-  1. Create the `Makefile' by typing:
-	 `./configure --prefix=/directory/where/you/want/the/module/file'
+  * Implicit type conversions between Python and Octave.  Supports all
+    Numeric integer, real double (and possibly real float) matrices
 
-  2. Type `make' to build the extention module.
+  * Architecture independent - no assumption on endian type or integer
+    sizes
 
-  3. To copy the pytave dynamic library to the prefix, type
-     `make install'
+  * Supports cell <-> list and struct <-> dict conversions.
 
-BJam
-====
+Project homepage
+================
 
-BJam must be installed in order to build the module. You also need a
-proper `user-config.jam' file in your home directory.
+https://launchpad.net/pytave
+
+Using/hacking
+=============
 
-  1. Create `Jamfile' and `project-root.jam' by typing `./configure'
+You need the Bazaar version control software (bzr).  Branch from trunk
+with:
 
-  2. Use your `bjam' command to build the extention module. 
+  $ bzr branch lp:pytave
 
-user-config.jam
-===============
+   You will now have a directory called `pytave' with source code for
+the module.  Read the INSTALL file for building instructions.
 
-For your convenience, here the content of a typical ~/user-config.jam
-on a GNU/Linux system:
+Gotchas
+*******
 
-using gcc ;
-using python : 2.5 ;
+Unfortunately, the implicit conversion is not bijective (there is not
+a one-to-one relation between Octave and Python values).  Pytave users
+should be aware of the following cases.
 
-Distutils
-=========
+Numeric row vectors to Octave matrices
+======================================
 
-  1. Create the `setup.py' file by typing `./configure'
+Numeric row vectors are converted to Octave 1xN matrices; returned 1xN
+matrices will become 1xN numerical arrays, not row vectors. As an
+example, a Numeric array with shape == (3,) will become (1, 3) when
+converted back and forth.
 
-  2. Run `python setup.py build' to build and package the extention
-     module together with the pure Python files.
-
-Running from build directory
+Octave cells to Python lists
 ============================
 
-Pytave is made up of three parts. The `pytave' package, the
-`pytave/pytave' module and the `pytave/_pytave' extention. When the
-user uses `import pytave', the pytave package __init__ script loads
-both the module and the extention. It is important that they both can
-be found. 
+Only row cell arrays can be converted to Python lists.
+
+Python dictionaries to Octave structures
+========================================
+
+Dictionaries converted to structures must only have string keys.  This
+is because Octave structures only allow string keys.  Keys must also
+be valid Octave identifiers.
+
+   As Octave structures are built using cells, simple variables are
+upgraded to cells when a dictionary is converted.  A dictionary
 
-  1. Follow the Distutils build instructions. A complete Python
-     package directory called `pytave' is created in
-     `build/lib.something'
+{"name": "Pytave"}
+
+thus will become
 
-  2. Start the Python interactive interpreter with
-     `PYTHONPATH=build/lib.linux-i686-2.4/ python' (with appropiate
-     changes for your system.)
+ans =
+{
+  name = Pytave
+}
+
+in Octave.  In this listing, Octave is hiding the fact that the value
+is wrapped in a cell.  Converted back, cells are converted to Python
+lists. The re-converted Python dictionary will read
 
-  3. In the interpreter you can now access Octave through Python:
+{"name": ["Pytave"]}
+
+which is natural effect because of the way Octave handles structures.
+
+   The list values in dictionaries to be converted must be of equal
+length.  All restrictions demanded by the Octave `struct' built-in
+applies.
+
+Pytave and multi-threading
+**************************
 
-import pytave
-import Numeric
-pytave.feval(1, "cos", 0)
-b = pytave.addpath(".")
-pytave.feval(1, "testfile", 42)
+Pytave does not handle reentrant calls.  It is not thread-safe, and
+you cannot make several Pytave calls in parallel.  There are no safety
+harnesses in Pytave (unlike e.g. PySqlite), and Pytave will not stop
+you if you try to make concurrent calls.  The behavior is undefined.
+It is not possible to run several calculations in parallel.
 
-     (Observe that there is a testfile.m file in the distribution.)
+   That being said, it is possible to do other things while one Pytave
+call is running.  Pytave is aware of the Global Interpreter Lock.  The
+lock will be released while the Octave interpreter is running,
+allowing you to have other Python threads to run in parallel with the
+one Octave call.
 
-    Using BJam or Automake instead of Distutils, you load the
-`pytave/pytave' module and the extention instead of the whole
-package. Using `import pytave' now calls the module directly, but the
-difference is transparent to the user.
+Python/Octave cheat sheet
+*************************
 
-    Basically all you want to do is load Python with shared library
-for the pytave extention (called `pytave/_pytave') and the native
-`pytave/pytave' module. BJam creates shared library in the
-`bin/something/something' directory, while Autotools hide a working
-shared library in the `.libs' directory. The contents of the `pytave'
-package is stored in the directory `package' of the source
-package. This is an example for an Autotools build.
+Octave and Python share some syntax elements, which unfortunately
+makes it harder to distinguish between the languages.  Here are some
+examples in both languages, showing how to build related constructs.
+
+Create a 2x3 matrix
+===================
+
+octave:1> [1, 1, 1; 2, 2, 2]
+python>>> array([[1, 1, 1], [2, 2, 2]])
+
+Create a 3x2 matrix
+===================
 
-  1. Follow the Autotools build instructions.
+octave:1> [1, 1; 2, 2; 3, 3]
+python>>> array([[1, 1], [2, 2], [3, 3]])
+
+Create a 1x3 matrix
+===================
 
-  2. Start the Python interpreter with a Python path set to a path
-     containing `_pytave.so' and the `package' directory. A common way
-     to do this with the bash shell is to execute this command:
-     `PYTHONPATH=.libs:package python'.
+octave:1> [1, 1, 1]
+python>>> array([[1, 1, 1]])
 
-Installing with distutils
-=========================
+Create a row vector
+===================
+
+Not applicable to Octave.
+python>>> array([1, 1, 1])
 
-  1. Run `python setup.py install'
+Note: Python row vectors will be converted to Octave 1xN matrices.
 
-Creating a source dist
-======================
+Create a 3x1 matrix
+===================
 
-  1. Run `make distcheck'
+octave:1> [1; 2; 3]
+python>>> array([[1], [2], [3]])
 
-Hint about foreign systems
-==========================
+Create a 1x1 structure/dictionary
+=================================
+
+octave:1> struct("x", 1, "y", 2)
+python>>> {"x": 1, "y": 2}
 
-If you are running on a system incapable of executing the configure
-scripts (e.g. a Microsoft Windows system), you may want to try
-installing the `MinGW' and `MSYS' packages, and build everything
-inside that environment. This isn't for the faint of hearted though,
-since you need/want to build Octave too. It is probably easier than
-trying to build without configure scripts, that's all. There are no
-guarentees that it will build at all, it has not been tested.
+Create a 1x2 structure array/dictionary containing lists of length 2
+====================================================================
+
+octave:1> struct("firstname", {"David", "Håkan"}, ...
+                 "lastname", {"Grundberg", "Fors Nilsson"})
+python>>> {"firstname": ["David", "Håkan"], \
+           "lastname": ["Grundberg", "Fors Nilsson"]}
 
-EOF.
\ No newline at end of file
+Create a 1x3 cell array/list
+============================
+
+octave:1> {"foo", "bar", "baz"}
+python>>> ["foo", "bar", "baz"]
+
+EOF.
--- a/configure.ac	Mon Nov 17 12:19:57 2008 +0100
+++ b/configure.ac	Tue May 05 21:11:40 2009 +0200
@@ -17,105 +17,35 @@
 
 AC_PRESERVE_HELP_ORDER
 
-# Look for Octave package
-AC_MSG_CHECKING([for Octave package])
-AC_ARG_WITH([octave],
-            [AS_HELP_STRING([--with-octave],
-                            [Optionally set Octave package to use.
-                            @<:@default=check@:>@])],
-            [with_octave=$withval],
-            [with_octave=check])
-AS_IF([test "x$with_octave" == xno],
-[
-   AC_MSG_FAILURE([--without-octave was given but Octave required])
-], [])
-
-AS_IF([test "x$with_octave" == xyes],
-[
-   with_octave=check
-], [])
-
-AS_IF([test "x$with_octave" == xcheck],
-[
-   AC_PATH_TOOL(octaveconfig, octave-config, [eepnotfound])
-],
-[
-   AC_PATH_TOOL(octaveconfig, octave-config, [eepnotfound], $with_octave/bin)
-])
+pytave_libs_ok=
 
-AS_IF([test "x$octaveconfig" == "xeepnotfound"],
-[
-   AC_MSG_WARN([Could not find octave-config.])
-],
-[
-   PYTAVE_OCTAVE_RPATH=`$octaveconfig -p OCTLIBDIR`
-   PYTAVE_OCTAVE_INCLUDE_PATH=`$octaveconfig -p OCTINCLUDEDIR`
-   AC_MSG_RESULT([  results of the Octave check:])
-   AC_MSG_RESULT([    octave-config: $octaveconfig])
-   AC_MSG_RESULT([    Library:       $PYTAVE_OCTAVE_RPATH])
-   AC_MSG_RESULT([    Include Dir:   $PYTAVE_OCTAVE_INCLUDE_PATH])
-
-   # Try to compile and link against Octave libraries.
-   old_flags="$LDFLAGS"
-   LDFLAGS="-L$PYTAVE_OCTAVE_RPATH $LDFLAGS"
-
-   old_cxx="$CPPFLAGS"
-   CPPFLAGS="-I$PYTAVE_OCTAVE_INCLUDE_PATH $CXXFLAGS"
-
-   old_libs="$LIBS"
-   LIBS="-loctave -lcruft -loctinterp $LIBS"
-
-   AC_CACHE_CHECK([whether linking to Octave library works], [pytave_cv_lib_octave],
-   [
-      pytave_cv_lib_octave=no
-      AC_LANG_ASSERT(C++)
-      AC_LINK_IFELSE(
-         AC_LANG_PROGRAM(
-            [[#include <octave/oct.h>
-              #include <octave/Matrix.h> ]],
-            [[MatrixType()]]),
-         [pytave_cv_lib_octave=yes],
-         [pytave_cv_lib_octave=no])
-   ])
-
-
-   LDFLAGS="$old_flags"
-   LIBS="$old_libs"
-   CPPFLAGS="$old_cpp"
-
-
-])
+AX_OCTAVE([], [], [pytave_libs_ok=no])
+AX_PYTHON_DEVEL([], [], [pytave_libs_ok=no])
 
 # Look for boost::python
-AX_PYTHON()
-old_libs="$LIBS"
-AS_IF([test "x$PYTHON_LIB" != "x"],[
-LIBS="-l$PYTHON_LIB $LIBS"
-],[])
-AX_BOOST_PYTHON()
-LIBS="$old_libs"
+pytave_old_libs="$LIBS"
+pytave_old_ldflags="$LDFLAGS"
+pytave_old_cppflags="$CPPFLAGS"
+LIBS="$LIBS $PYTHON_LIBS"
+LDFLAGS="$LDFLAGS $PYTHON_LDFLAGS"
+CPPFLAGS="$CPPFLAGS $PYTHON_CPPFLAGS"
 
-# Now check the two vital libs, if they have problems, halt.
-pytave_fatal_errors=no
+AX_BOOST_PYTHON([], [pytave_libs_ok=no])
 
-AS_IF(test "x$pytave_cv_lib_octave" != "xyes",
+LIBS="$pytave_old_libs"
+LDFLAGS="$pytave_old_ldflags"
+CPPFLAGS="$pytave_old_cppflags"
+
+# Now check the libs, if they have problems, halt.
+AS_IF(test -n "$pytave_libs_ok",
 [
-   AC_MSG_WARN([Linking to Octave failed.])
-   pytave_fatal_errors=yes
-], [])
+   AC_MSG_ERROR([
+========================================================================
+One or more library dependencies could not be resolved.
 
-AS_IF(test "x$BOOST_PYTHON_LIB" == "x",
-[
-   AC_MSG_WARN([Cannot find Boost::Python lib.])
-   pytave_fatal_errors=yes
-], [])
-
-
-AS_IF(test "x$pytave_fatal_errors" == "xyes",
-[
-   AC_MSG_ERROR([Configuration failed. Halt.])
-], [])
-
+Configuration failed. Halt.
+========================================================================])
+])
 
 # Do some more initializations
 
@@ -148,16 +78,16 @@
 ])
 
 # Substitutes for the Makefile/Jamfile
-AC_SUBST(PYTAVE_OCTAVE_INCLUDE_PATH)
+#AC_SUBST(OCTAVE_INCLUDEDIR)
+#AC_SUBST(OCTAVE_LIBRARYDIR)
+PYTAVE_OCTAVE_RPATH="$OCTAVE_LIBRARYDIR"
 AC_SUBST(PYTAVE_OCTAVE_RPATH)
 AC_SUBST(PYTAVE_MODULE_INSTALL_PATH)
 
 # Substitutes for the Jamfile. XXX: Replace lib*.so with OS independent name.
-AC_SUBST(JAM_LIBOCTAVE, $PYTAVE_OCTAVE_RPATH/liboctave.so)
-AC_SUBST(JAM_LIBCRUFT, $PYTAVE_OCTAVE_RPATH/libcruft.so)
-AC_SUBST(JAM_LIBOCTINTERP, $PYTAVE_OCTAVE_RPATH/liboctinterp.so)
+AC_SUBST(JAM_LIBOCTAVE, $OCTAVE_LIBRARYDIR/liboctave.so)
+AC_SUBST(JAM_LIBCRUFT, $OCTAVE_LIBRARYDIR/libcruft.so)
+AC_SUBST(JAM_LIBOCTINTERP, $OCTAVE_LIBRARYDIR/liboctinterp.so)
 
-# Substitute in these files
-AC_OUTPUT([Makefile Jamfile setup.py])
-# Copy project-root.jam to VPATH too
-AC_OUTPUT([project-root.jam])
+# Substitute in these files, copy project-root.jam to VPATH too
+AC_OUTPUT([Makefile Jamfile setup.py project-root.jam])
--- a/exceptions.h	Mon Nov 17 12:19:57 2008 +0100
+++ b/exceptions.h	Tue May 05 21:11:40 2009 +0200
@@ -38,8 +38,9 @@
    class octave_error_exception {
       public:
          static bool init() {
-            excclass = PyErr_NewException("pytave.OctaveError",
-                                          PyExc_RuntimeError, NULL);
+            excclass = PyErr_NewException(
+               const_cast<char*>("pytave.OctaveError"),
+               PyExc_RuntimeError, NULL);
             return excclass != NULL;
          };
          static void translate_exception(octave_error_exception const &py_ex) {
@@ -57,8 +58,9 @@
    class value_convert_exception {
       public:
          static bool init() {
-            excclass = PyErr_NewException("pytave.ValueConvertError",
-                                          PyExc_TypeError, NULL);
+            excclass = PyErr_NewException(
+               const_cast<char*>("pytave.ValueConvertError"),
+               PyExc_TypeError, NULL);
             return excclass != NULL;
          };
          static void translate_exception(value_convert_exception const &py_ex) {
@@ -75,8 +77,9 @@
    class object_convert_exception {
       public:
          static bool init() {
-            excclass = PyErr_NewException("pytave.ObjectConvertError",
-                                          PyExc_TypeError, NULL);
+            excclass = PyErr_NewException(
+               const_cast<char*>("pytave.ObjectConvertError"),
+               PyExc_TypeError, NULL);
             return excclass != NULL;
          };
          static void translate_exception(
--- a/m4/ax_boost_python.m4	Mon Nov 17 12:19:57 2008 +0100
+++ b/m4/ax_boost_python.m4	Tue May 05 21:11:40 2009 +0200
@@ -4,7 +4,7 @@
 #
 # SYNOPSIS
 #
-#   AX_BOOST_PYTHON
+#   AX_BOOST_PYTHON([ACTION_IF_FOUND], [ACTION_IF_NOT_FOUND])
 #
 # DESCRIPTION
 #
@@ -18,15 +18,13 @@
 #
 #   This macro calls AC_SUBST(BOOST_PYTHON_LIB).
 #
-#   In order to ensure that the Python headers are specified on the include
-#   path, this macro requires AX_PYTHON to be called.
-#
 # LAST MODIFICATION
 #
-#   2008-04-12
+#   2009-04-04
 #
 # COPYLEFT
 #
+#   Copyright (c) 2009 David Grundberg
 #   Copyright (c) 2008 Michael Tindal
 #
 #   This program is free software; you can redistribute it and/or modify it
@@ -55,16 +53,14 @@
 #   distribute a modified version of the Autoconf Macro, you may extend this
 #   special exception to the GPL to apply to your modified version as well.
 
-AC_DEFUN([AX_BOOST_PYTHON],
-[AC_REQUIRE([AX_PYTHON])dnl
-AC_CACHE_CHECK(whether the Boost::Python library is available,
+AC_DEFUN([AX_BOOST_PYTHON], [
+AC_CACHE_CHECK([[whether the Boost::Python library is available]],
 ac_cv_boost_python,
-[AC_LANG_SAVE
+[
+ BOOST_PYTHON_LIB=
+ AC_LANG_SAVE
  AC_LANG_CPLUSPLUS
  CPPFLAGS_SAVE=$CPPFLAGS
- if test x$PYTHON_INCLUDE_DIR != x; then
-   CPPFLAGS=-I$PYTHON_INCLUDE_DIR $CPPFLAGS
- fi
  AC_COMPILE_IFELSE(AC_LANG_PROGRAM([[
  #include <boost/python/module.hpp>
  using namespace boost::python;
@@ -76,15 +72,24 @@
 ])
 if test "$ac_cv_boost_python" = "yes"; then
   AC_DEFINE(HAVE_BOOST_PYTHON,,[define if the Boost::Python library is available])
-  ax_python_lib=boost_python
-  AC_ARG_WITH([boost-python],AS_HELP_STRING([--with-boost-python],[specify the boost python library or suffix to use]),
-  [if test "x$with_boost_python" != "xno"; then
-     ax_python_lib=$with_boost_python
-     ax_boost_python_lib=boost_python-$with_boost_python
-   fi])
-  for ax_lib in $ax_python_lib $ax_boost_python_lib boost_python; do
+  ax_boost_python_lib=boost_python
+  AS_IF([test -n "$PYTHON_VERSION"], [
+     # Read ax_python_devel for info about the PYTHON_VERSION variable
+     ax_boost_python_lib=boost_python$PYTHON_VERSION
+  ])
+  AC_ARG_WITH([boost-python],AS_HELP_STRING([--with-boost-python],[specify the boost python library or suffix to use]), [
+    AS_IF([test "x$with_boost_python" != "xno"], [
+       ax_boost_python_lib=$with_boost_python
+    ])
+  ])
+  for ax_lib in $ax_boost_python_lib boost_python; do
     AC_CHECK_LIB($ax_lib, exit, [BOOST_PYTHON_LIB=$ax_lib break])
   done
   AC_SUBST(BOOST_PYTHON_LIB)
 fi
+
+if  test -n "$BOOST_PYTHON_LIB" ; then
+   m4_ifvaln([$1],[$1],[:])dnl
+   m4_ifvaln([$2],[else $2])dnl
+ fi
 ])dnl
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/m4/ax_octave.m4	Tue May 05 21:11:40 2009 +0200
@@ -0,0 +1,199 @@
+# ===========================================================================
+#
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AX_OCTAVE([OCTAVE_CONFIG], [ACTION_IF_FOUND], [ACTION_IF_NOT_FOUND])
+#
+# DESCRIPTION
+#
+#   This macro does a Octave development environment check.
+#
+#   It accepts one optional argument, OCTAVE_CONFIG.  This is the full
+#   path the the octave-config used to find out the environment.
+#
+#   If OCTAVE_CONFIG is not set, or empty, a octave-config executable
+#   is searched for using AC_PATH_TOOL.  If the executable is not
+#   found, or does not return results, the Octave interpreter will be
+#   used instead.
+#
+#   As a final check, a simple test program is compiled and linked
+#   against the found Octave installation.  If the check is
+#   successful, ACTION_IF_FOUND is executed, otherwise
+#   ACTION_IF_NOT_FOUND.
+#
+#   AX_OCTAVE substitutes OCTAVE_CPPFLAGS, OCTAVE_LDFLAGS and
+#   OCTAVE_LIBS, along with the optional OCTAVE_LIBRARYDIR and
+#   OCTAVE_INCLUDEDIR.
+#
+#   Typical usage:
+#
+#	AX_OCTAVE([], [], [
+#		AC_MSG_ERROR([[Octave required but not available]])
+#		])
+#	LIBS="$LIBS $OCTAVE_LIBS"
+#	CPPFLAGS="$CPPFLAGS $OCTAVE_CPPFLAGS"
+#	LDFLAGS="$LDFLAGS $OCTAVE_LDFLAGS"
+#
+# LAST MODIFICATION
+#
+#   2009-05-04
+#
+# COPYING
+#
+#   Copyright (c) 2009 David Grundberg
+#
+#   This program is free software; you can redistribute it and/or modify it
+#   under the terms of the GNU General Public License as published by the
+#   Free Software Foundation; either version 2 of the License, or (at your
+#   option) any later version.
+#
+#   This program is distributed in the hope that it will be useful, but
+#   WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+#   Public License for more details.
+#
+#   You should have received a copy of the GNU General Public License along
+#   with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+#   As a special exception, the respective Autoconf Macro's copyright owner
+#   gives unlimited permission to copy, distribute and modify the configure
+#   scripts that are the output of Autoconf when processing the Macro. You
+#   need not follow the terms of the GNU General Public License when using
+#   or distributing such scripts, even though portions of the text of the
+#   Macro appear in them. The GNU General Public License (GPL) does govern
+#   all other use of the material that constitutes the Autoconf Macro.
+#
+#   This special exception to the GPL applies to versions of the Autoconf
+#   Macro released by the Autoconf Macro Archive. When you make and
+#   distribute a modified version of the Autoconf Macro, you may extend this
+#   special exception to the GPL to apply to your modified version as well.
+
+AC_DEFUN([AX_OCTAVE],[
+	# These are the variables AX_OCTAVE uses
+	OCTAVE_LDFLAGS=
+	OCTAVE_LIBS=
+	OCTAVE_CPPFLAGS=
+	OCTAVE_INCLUDEDIR=
+	OCTAVE_LIBRARYDIR=
+	ax_octave_config="$1"
+	ax_octave_ok=
+
+	AC_MSG_CHECKING([for octave-config filename])
+	AS_IF([test -z "$ax_octave_config"], [
+		AC_MSG_RESULT([determined from path])
+		AC_PATH_TOOL([ax_octave_config], [octave-config], [])
+		AS_IF([test -z "$ax_octave_config"], [
+			AC_MSG_WARN([Could not find octave-config.])
+		], [])
+	], [
+		AC_MSG_RESULT([specified $ax_octave_config])
+	])
+
+	AS_IF([test -n "$ax_octave_config"], [
+		AC_MSG_CHECKING([for Octave library path])
+		OCTAVE_LIBRARYDIR=`$ax_octave_config -p OCTLIBDIR`
+		AC_MSG_RESULT([$OCTAVE_LIBRARYDIR])
+
+		AC_MSG_CHECKING([for Octave include path])
+		OCTAVE_INCLUDEDIR=`$ax_octave_config -p OCTINCLUDEDIR`
+		AC_MSG_RESULT([$OCTAVE_INCLUDEDIR])
+	])
+
+	AS_IF([[test -z "$OCTAVE_LIBRARYDIR" -o -z "$OCTAVE_INCLUDEDIR"]], [
+		AC_MSG_WARN([[
+========================================================================
+Octave library or include path not found using octave-config, trying
+Octave interpreter.
+
+This could be a sign that the Octave development package is missing.
+========================================================================]])
+
+		OCTAVE_LIBRARYDIR=
+		OCTAVE_INCLUDEDIR=
+
+		AC_MSG_NOTICE([[checking for Octave interpreter]])
+		AC_PATH_TOOL([ax_octave_interpreter], [octave], [])
+		AS_IF([test -z "$ax_octave_interpreter"], [
+			AC_MSG_WARN([Could not find Octave interpreter.])
+		], [
+			AC_MSG_CHECKING([for Octave library path (alt)])
+			OCTAVE_LIBRARYDIR=`$ax_octave_interpreter -q --eval "printf(octave_config_info.octlibdir)"`
+			AC_MSG_RESULT([$OCTAVE_LIBRARYDIR])
+
+			AC_MSG_CHECKING([for Octave include path (alt)])
+			OCTAVE_INCLUDEDIR=`$ax_octave_interpreter -q --eval "printf(octave_config_info.octincludedir)"`
+			AC_MSG_RESULT([$OCTAVE_INCLUDEDIR])
+		])
+
+		AS_IF([[test -z "$OCTAVE_LIBRARYDIR" -o -z "$OCTAVE_INCLUDEDIR"]], [
+			ax_octave_ok=no
+		])
+	])
+
+	AS_IF([test -z "$ax_octave_ok"], [
+		OCTAVE_LDFLAGS="-L$OCTAVE_LIBRARYDIR"
+		OCTAVE_LIBS="-loctave -lcruft -loctinterp"
+		OCTAVE_CPPFLAGS="-I$OCTAVE_INCLUDEDIR"
+
+		AC_CACHE_CHECK([whether linking to Octave library works], [ax_octave_cv_lib_octave],
+		[
+			ax_octave_cv_lib_octave=no
+
+			AC_LANG_PUSH([C++])
+
+			ax_octave_old_ldflags="$LDFLAGS"
+			ax_octave_old_cppflags="$CPPFLAGS"
+			ax_octave_old_libs="$LIBS"
+			LDFLAGS="$OCTAVE_LDFLAGS $LDFLAGS"
+			CPPFLAGS="$OCTAVE_CPPFLAGS $CPPFLAGS"
+			LIBS="$OCTAVE_LIBS $LIBS"
+
+			AC_LANG_ASSERT(C++)
+			AC_LINK_IFELSE(
+			AC_LANG_PROGRAM(
+				[[#include <octave/oct.h>
+				#include <octave/Matrix.h> ]],
+				[[MatrixType()]]),
+				[ax_octave_cv_lib_octave=yes],
+				[ax_octave_cv_lib_octave=no])
+			LDFLAGS="$ax_octave_old_ldflags"
+			CPPFLAGS="$ax_octave_old_cppflags"
+			LIBS="$ax_octave_old_libs"
+
+			AC_LANG_POP([C++])
+		])
+		AS_IF([test "x$ax_octave_cv_lib_octave" != "xyes"], [
+			ax_octave_ok=no
+		])
+	])
+
+	AS_IF([test -n "$ax_octave_ok"], [
+		OCTAVE_LDFLAGS=
+		OCTAVE_LIBS=
+		OCTAVE_CPPFLAGS=
+		OCTAVE_INCLUDEDIR=
+		OCTAVE_LIBRARYDIR=
+
+		AC_MSG_WARN([[
+========================================================================
+Can not link with Octave.
+
+Make sure the Octave development package is installed.
+========================================================================]])
+	])
+
+	AC_SUBST([OCTAVE_LDFLAGS])
+	AC_SUBST([OCTAVE_CPPFLAGS])
+	AC_SUBST([OCTAVE_LIBS])
+	AC_SUBST([OCTAVE_INCLUDEDIR])
+	AC_SUBST([OCTAVE_LIBRARYDIR])
+
+	# Execute ACTION_IF_FOUND or ACTION_IF_NOT_FOUND
+	if test -z "$ax_octave_ok" ; then
+		m4_ifvaln([$2],[$2],[:])dnl
+		m4_ifvaln([$3],[else $3])dnl
+	fi
+
+])
--- a/m4/ax_python.m4	Mon Nov 17 12:19:57 2008 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,99 +0,0 @@
-# ===========================================================================
-#               http://autoconf-archive.cryp.to/ax_python.html
-# ===========================================================================
-#
-# SYNOPSIS
-#
-#   AX_PYTHON
-#
-# DESCRIPTION
-#
-#   This macro does a complete Python development environment check.
-#
-#   It recurses through several python versions (from 2.1 to 2.5 in this
-#   version), looking for an executable. When it finds an executable, it
-#   looks to find the header files and library.
-#
-#   It sets PYTHON_BIN to the name of the python executable,
-#   PYTHON_INCLUDE_DIR to the directory holding the header files, and
-#   PYTHON_LIB to the name of the Python library.
-#
-#   This macro calls AC_SUBST on PYTHON_BIN (via AC_CHECK_PROG),
-#   PYTHON_INCLUDE_DIR and PYTHON_LIB.
-#
-# LAST MODIFICATION
-#
-#   2008-04-12
-#
-# COPYLEFT
-#
-#   Copyright (c) 2008 Michael Tindal
-#
-#   This program is free software; you can redistribute it and/or modify it
-#   under the terms of the GNU General Public License as published by the
-#   Free Software Foundation; either version 2 of the License, or (at your
-#   option) any later version.
-#
-#   This program is distributed in the hope that it will be useful, but
-#   WITHOUT ANY WARRANTY; without even the implied warranty of
-#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
-#   Public License for more details.
-#
-#   You should have received a copy of the GNU General Public License along
-#   with this program. If not, see <http://www.gnu.org/licenses/>.
-#
-#   As a special exception, the respective Autoconf Macro's copyright owner
-#   gives unlimited permission to copy, distribute and modify the configure
-#   scripts that are the output of Autoconf when processing the Macro. You
-#   need not follow the terms of the GNU General Public License when using
-#   or distributing such scripts, even though portions of the text of the
-#   Macro appear in them. The GNU General Public License (GPL) does govern
-#   all other use of the material that constitutes the Autoconf Macro.
-#
-#   This special exception to the GPL applies to versions of the Autoconf
-#   Macro released by the Autoconf Macro Archive. When you make and
-#   distribute a modified version of the Autoconf Macro, you may extend this
-#   special exception to the GPL to apply to your modified version as well.
-
-AC_DEFUN([AX_PYTHON],
-[AC_MSG_CHECKING(for python build information)
-AC_MSG_RESULT([])
-for python in python2.4 python2.5 python2.3 python2.2 python2.1 python; do
-AC_CHECK_PROGS(PYTHON_BIN, [$python])
-ax_python_bin=$PYTHON_BIN
-if test "x$ax_python_bin" != "x"; then
-   AC_CHECK_LIB($ax_python_bin, main, ax_python_lib=$ax_python_bin, ax_python_lib=no)
-   AC_CHECK_HEADER([$ax_python_bin/Python.h],
-   [[ax_python_header=`locate "$ax_python_bin/Python.h" | sed -e s,/Python.h,,`]],
-   ax_python_header=no)
-   if test "$ax_python_lib" != no; then
-     if test "$ax_python_header" != no; then
-       break;
-     fi
-   fi
-fi
-done
-if test x$ax_python_bin = x; then
-   ax_python_bin=no
-fi
-if test x$ax_python_header = x; then
-   ax_python_header=no
-fi
-if test x$ax_python_lib = x; then
-   ax_python_lib=no
-fi
-
-AC_MSG_RESULT([  results of the Python check:])
-AC_MSG_RESULT([    Binary:      $ax_python_bin])
-AC_MSG_RESULT([    Library:     $ax_python_lib])
-AC_MSG_RESULT([    Include Dir: $ax_python_header])
-
-if test x$ax_python_header != xno; then
-  PYTHON_INCLUDE_DIR=$ax_python_header
-  AC_SUBST(PYTHON_INCLUDE_DIR)
-fi
-if test x$ax_python_lib != xno; then
-  PYTHON_LIB=$ax_python_lib
-  AC_SUBST(PYTHON_LIB)
-fi
-])dnl
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/m4/ax_python_devel.m4	Tue May 05 21:11:40 2009 +0200
@@ -0,0 +1,338 @@
+# ===========================================================================
+#
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AX_PYTHON_DEVEL([version], [ACTION_IF_FOUND], [ACTION_IF_NOT_FOUND])
+#
+# DESCRIPTION
+#
+#   Note: Defines as a precious variable "PYTHON_VERSION". Don't override it
+#   in your configure.ac.
+#
+#   This macro checks for Python and tries to get the include path to
+#   'Python.h'. It provides the $(PYTHON_CPPFLAGS), $(PYTHON_LIBS) and
+#   $(PYTHON_LDFLAGS) output variables. It also exports
+#   $(PYTHON_EXTRA_LIBS) and $(PYTHON_EXTRA_LDFLAGS) for embedding
+#   Python in your code.
+#
+#   You can search for some particular version of Python by passing a
+#   parameter to this macro, for example ">= '2.3.1'", or "== '2.4'". Please
+#   note that you *have* to pass also an operator along with the version to
+#   match, and pay special attention to the single quotes surrounding the
+#   version number. Don't use "PYTHON_VERSION" for this: that environment
+#   variable is declared as precious and thus reserved for the end-user.
+#
+#   This macro should work for all versions of Python >= 2.1.0. As an end
+#   user, you can disable the check for the python version by setting the
+#   PYTHON_NOVERSIONCHECK environment variable to something else than the
+#   empty string.
+#
+#   As a final check, a simple test program is compiled and linked
+#   against the found Python installation.  If the check is
+#   successful, ACTION_IF_FOUND is executed, otherwise
+#   ACTION_IF_NOT_FOUND.
+#
+# LICENSE
+#
+#   Copyright (c) 2009 David Grundberg
+# Derived from http://www.nongnu.org/autoconf-archive/ac_python_devel.html
+#   Copyright (c) 2009 Sebastian Huber <sebastian-huber@web.de>
+#   Copyright (c) 2009 Alan W. Irwin <irwin@beluga.phys.uvic.ca>
+#   Copyright (c) 2009 Rafael Laboissiere <rafael@laboissiere.net>
+#   Copyright (c) 2009 Andrew Collier <colliera@ukzn.ac.za>
+#   Copyright (c) 2009 Matteo Settenvini <matteo@member.fsf.org>
+#   Copyright (c) 2009 Horst Knorr <hk_classes@knoda.org>
+#
+#   This program is free software: you can redistribute it and/or modify it
+#   under the terms of the GNU General Public License as published by the
+#   Free Software Foundation, either version 3 of the License, or (at your
+#   option) any later version.
+#
+#   This program is distributed in the hope that it will be useful, but
+#   WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+#   Public License for more details.
+#
+#   You should have received a copy of the GNU General Public License along
+#   with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+#   As a special exception, the respective Autoconf Macro's copyright owner
+#   gives unlimited permission to copy, distribute and modify the configure
+#   scripts that are the output of Autoconf when processing the Macro. You
+#   need not follow the terms of the GNU General Public License when using
+#   or distributing such scripts, even though portions of the text of the
+#   Macro appear in them. The GNU General Public License (GPL) does govern
+#   all other use of the material that constitutes the Autoconf Macro.
+#
+#   This special exception to the GPL applies to versions of the Autoconf
+#   Macro released by the Autoconf Archive. When you make and distribute a
+#   modified version of the Autoconf Macro, you may extend this special
+#   exception to the GPL to apply to your modified version as well.
+
+AC_DEFUN([AX_PYTHON_DEVEL],[
+	#
+	# Allow the use of a (user set) custom python version
+	#
+	AC_ARG_VAR([PYTHON_VERSION],[The installed Python
+		version to use, for example '2.3'. This string
+		will be appended to the Python interpreter
+		canonical name.])
+
+	AC_PATH_PROG([PYTHON],[python[$PYTHON_VERSION]])
+	if test -z "$PYTHON"; then
+	   AC_MSG_ERROR([Cannot find python$PYTHON_VERSION in your system path])
+	   PYTHON_VERSION=""
+	fi
+
+	#
+	# Check for a version of Python >= 2.1.0
+	#
+	AC_MSG_CHECKING([for a version of Python >= '2.1.0'])
+	ac_supports_python_ver=`$PYTHON -c "import sys; \
+		ver = sys.version.split ()[[0]]; \
+		print (ver >= '2.1.0')"`
+	if test "$ac_supports_python_ver" != "True"; then
+		if test -z "$PYTHON_NOVERSIONCHECK"; then
+			AC_MSG_RESULT([no])
+			AC_MSG_FAILURE([
+This version of the AC@&t@_PYTHON_DEVEL macro doesn't work properly
+with versions of Python before 2.1.0. You may need to re-run
+configure, setting the variables PYTHON_CPPFLAGS, PYTHON_LDFLAGS,
+PYTHON_LIBS, PYTHON_SITE_PKG, PYTHON_EXTRA_LIBS and
+PYTHON_EXTRA_LDFLAGS by hand.  Moreover, to disable this check, set
+PYTHON_NOVERSIONCHECK to something else than an empty string.
+])
+		else
+			AC_MSG_RESULT([skip at user request])
+		fi
+	else
+		AC_MSG_RESULT([yes])
+	fi
+
+	#
+	# if the macro parameter ``version'' is set, honour it
+	#
+	if test -n "$1"; then
+		AC_MSG_CHECKING([for a version of Python $1])
+		ac_supports_python_ver=`$PYTHON -c "import sys; \
+			ver = sys.version.split ()[[0]]; \
+			print (ver $1)"`
+		if test "$ac_supports_python_ver" = "True"; then
+	   	   AC_MSG_RESULT([yes])
+		else
+			AC_MSG_RESULT([no])
+			AC_MSG_ERROR([this package requires Python $1.
+If you have it installed, but it isn't the default Python
+interpreter in your system path, please pass the PYTHON_VERSION
+variable to configure. See ``configure --help'' for reference.
+])
+			PYTHON_VERSION=""
+		fi
+	fi
+
+	#
+	# Check if you have distutils, else fail
+	#
+	AC_MSG_CHECKING([for the distutils Python package])
+	ac_distutils_result=`$PYTHON -c "import distutils" 2>&1`
+	if test -z "$ac_distutils_result"; then
+		AC_MSG_RESULT([yes])
+	else
+		AC_MSG_RESULT([no])
+		AC_MSG_ERROR([cannot import Python module "distutils".
+Please check your Python installation. The error was:
+$ac_distutils_result])
+		PYTHON_VERSION=""
+	fi
+
+	#
+	# Check for Python include path
+	#
+	AC_MSG_CHECKING([for Python include path])
+	if test -z "$PYTHON_CPPFLAGS"; then
+		python_path=`$PYTHON -c "import distutils.sysconfig; \
+           		print (distutils.sysconfig.get_python_inc ());"`
+		if test -n "${python_path}"; then
+		   	python_path="-I$python_path"
+		fi
+		PYTHON_CPPFLAGS=$python_path
+	fi
+	AC_MSG_RESULT([$PYTHON_CPPFLAGS])
+	AC_SUBST([PYTHON_CPPFLAGS])
+
+	#
+	# Check for Python library path
+	#
+	AC_MSG_CHECKING([for Python library path])
+	if test -z "$PYTHON_LDFLAGS"; then
+		# (makes two attempts to ensure we've got a version number
+		# from the interpreter)
+		ac_python_version=`cat<<EOD | $PYTHON -
+
+# join all versioning strings, on some systems
+# major/minor numbers could be in different list elements
+from distutils.sysconfig import *
+ret = ''
+for e in get_config_vars ('VERSION'):
+	if (e != None):
+		ret += e
+print (ret)
+EOD`
+
+		if test -z "$ac_python_version"; then
+			if test -n "$PYTHON_VERSION"; then
+				ac_python_version=$PYTHON_VERSION
+			else
+				ac_python_version=`$PYTHON -c "import sys; \
+					print (sys.version[[:3]])"`
+			fi
+		fi
+
+		# Make the versioning information available to the compiler
+		AC_DEFINE_UNQUOTED([HAVE_PYTHON], ["$ac_python_version"],
+                                   [If available, contains the Python version number currently in use.])
+
+		# First, the library directory:
+		ac_python_libdir=`cat<<EOD | $PYTHON -
+
+# There should be only one
+import distutils.sysconfig
+for e in distutils.sysconfig.get_config_vars ('LIBDIR'):
+	if e != None:
+		print (e)
+		break
+EOD`
+
+		# Before checking for libpythonX.Y, we need to know
+		# the extension the OS we're on uses for libraries
+		# (we take the first one, if there's more than one fix me!):
+		ac_python_soext=`$PYTHON -c \
+		  "import distutils.sysconfig; \
+		  print (distutils.sysconfig.get_config_vars('SO')[[0]])"`
+
+		# Now, for the library:
+		ac_python_soname=`$PYTHON -c \
+		  "import distutils.sysconfig; \
+		  print (distutils.sysconfig.get_config_vars('LDLIBRARY')[[0]])"`
+
+		# Strip away extension from the end to canonicalize its name:
+		ac_python_library=`echo "$ac_python_soname" | sed "s/${ac_python_soext}$//"`
+
+		# This small piece shamelessly adapted from PostgreSQL python macro;
+		# credits goes to momjian, I think. I'd like to put the right name
+		# in the credits, if someone can point me in the right direction... ?
+		#
+		if test -n "$ac_python_libdir" -a -n "$ac_python_library" \
+			-a x"$ac_python_library" != x"$ac_python_soname"
+		then
+			# use the official shared library
+			ac_python_library=`echo "$ac_python_library" | sed "s/^lib//"`
+			PYTHON_LDFLAGS="-L$ac_python_libdir"
+			PYTHON_LIBS="-l$ac_python_library"
+		else
+			# old way: use libpython from python_configdir
+			ac_python_libdir=`$PYTHON -c \
+			  "from distutils.sysconfig import get_python_lib as f; \
+			  import os; \
+			  print (os.path.join(f(plat_specific=1, standard_lib=1), 'config'));"`
+			PYTHON_LDFLAGS="-L$ac_python_libdir"
+			PYTHON_LIBS="-lpython$ac_python_version"
+		fi
+
+		PYTHON_LIBDIR=$ac_python_libdir
+
+		if test -z "$PYTHON_LDFLAGS" -o -z "$PYTHON_LIBS"; then
+			AC_MSG_WARN([
+Cannot determine location of your Python DSO. Please check it was
+installed with dynamic libraries enabled, or try setting
+PYTHON_LDFLAGS and PYTHON_LIBS by hand.
+			])
+		fi
+	fi
+	AC_MSG_RESULT([$PYTHON_LDFLAGS $PYTHON_LIBS])
+	AC_SUBST([PYTHON_LDFLAGS])
+	AC_SUBST([PYTHON_LIBS])
+	AC_SUBST([PYTHON_LIBDIR])
+
+	#
+	# Check for site packages
+	#
+	AC_MSG_CHECKING([for Python site-packages path])
+	if test -z "$PYTHON_SITE_PKG"; then
+		PYTHON_SITE_PKG=`$PYTHON -c "import distutils.sysconfig; \
+		        print (distutils.sysconfig.get_python_lib(0,0));"`
+	fi
+	AC_MSG_RESULT([$PYTHON_SITE_PKG])
+	AC_SUBST([PYTHON_SITE_PKG])
+
+	#
+	# libraries which must be linked in when embedding
+	#
+	AC_MSG_CHECKING(python extra libraries)
+	if test -z "$PYTHON_EXTRA_LIBS"; then
+	   PYTHON_EXTRA_LIBS=`$PYTHON -c "import distutils.sysconfig; \
+                conf = distutils.sysconfig.get_config_var; \
+                print (conf('LOCALMODLIBS') + ' ' + conf('LIBS'))"`
+	fi
+	AC_MSG_RESULT([$PYTHON_EXTRA_LIBS])
+	AC_SUBST(PYTHON_EXTRA_LIBS)
+
+	#
+	# linking flags needed when embedding
+	#
+	AC_MSG_CHECKING(python extra linking flags)
+	if test -z "$PYTHON_EXTRA_LDFLAGS"; then
+		PYTHON_EXTRA_LDFLAGS=`$PYTHON -c "import distutils.sysconfig; \
+			conf = distutils.sysconfig.get_config_var; \
+			print (conf('LINKFORSHARED'))"`
+	fi
+	AC_MSG_RESULT([$PYTHON_EXTRA_LDFLAGS])
+	AC_SUBST(PYTHON_EXTRA_LDFLAGS)
+
+	#
+	# final check to see if everything compiles alright
+	#
+	AC_MSG_CHECKING([consistency of all components of python development environment])
+	# save current global flags
+	LDFLAGS="$ac_save_LDFLAGS $PYTHON_LDFLAGS $PYTHON_EXTRA_LDFLAGS $PYTHON_EXTRA_LIBS"
+	LIBS="$ac_save_LIBS $PYTHON_LIBS"
+	CPPFLAGS="$ac_save_CPPFLAGS $PYTHON_CPPFLAGS"
+	AC_LANG_PUSH([C])
+	AC_LINK_IFELSE([
+		AC_LANG_PROGRAM([[#include <Python.h>]],
+				[[Py_Initialize();]])
+		],[pythonexists=yes],[pythonexists=no])
+	AC_LANG_POP([C])
+	# turn back to default flags
+	CPPFLAGS="$ac_save_CPPFLAGS"
+	LDFLAGS="$ac_save_LDFLAGS"
+	LIBS="$ac_save_LIBS"
+
+	AC_MSG_RESULT([$pythonexists])
+
+        if test ! "x$pythonexists" = "xyes"; then
+	   AC_MSG_WARN([
+========================================================================
+Could not link test program to Python. Maybe the main Python library
+has been installed in some non-standard library path. If so, pass it
+to configure, via the LDFLAGS environment variable.
+
+Example: ./configure LDFLAGS="-L/usr/non-standard-path/python/lib"
+
+ERROR!
+You probably have to install the development version of the Python
+package for your distribution.  The exact name of this package varies
+among them.
+========================================================================])
+	  PYTHON_VERSION=""
+	  # Execute ACTION_IF_NOT_FOUND or ACTION_IF_FOUND
+	  m4_ifvaln([$3],[$3],[:])dnl
+	  m4_ifvaln([$2],[else $2])dnl
+	fi
+
+	#
+	# all done!
+	#
+])
--- a/octave_to_python.cc	Mon Nov 17 12:19:57 2008 +0100
+++ b/octave_to_python.cc	Tue May 05 21:11:40 2009 +0200
@@ -24,6 +24,7 @@
 #include <octave/oct.h>
 #include <octave/Matrix.h>
 #include <octave/ov.h>
+#include <octave/oct-map.h>
 
 #include <iostream>
 #include "pytavedefs.h"
@@ -42,6 +43,9 @@
 
 namespace pytave {
 
+   void octvalue_to_pyobj(boost::python::object &py_object,
+                          const octave_value& octvalue);
+
    template <class PythonPrimitive, class OctaveBase>
    static void copy_octarray_to_pyarrobj(
                                   PyArrayObject *pyarr,
@@ -171,7 +175,7 @@
 
    template <class CLASS, size_t bytes>
    inline static PyArrayObject *create_sint_array(CLASS value) {
-      if (bytes == sizeof(long)) { 
+      if (bytes == sizeof(long)) {
          return create_array<long, CLASS>(value, PyArray_LONG);
       } else if (bytes == sizeof(int)) {
          return create_array<signed int, CLASS>(value, PyArray_INT);
@@ -250,9 +254,45 @@
       py_object = object(handle<PyObject>((PyObject *)pyarr));
    }
 
+
+   static void octcell_to_pyobject(boost::python::object &py_object,
+                                   const Cell& cell) {
+      py_object = boost::python::list();
+
+      if(cell.dim1() != 1) {
+         throw value_convert_exception(
+            "Only one-dimensional (row mayor) cell arrays can be converted.");
+      }
+
+      for(octave_idx_type i = 0 ; i < cell.length(); i++) {
+         boost::python::object py_val;
+
+         octvalue_to_pyobj(py_val, cell.elem(i));
+
+         ((boost::python::list&)py_object).insert(i, py_val);
+      }
+   }
+
+   static void octmap_to_pyobject(boost::python::object &py_object,
+                                  const Octave_map& map) {
+      py_object = boost::python::dict();
+      string_vector keys = map.keys();
+
+      for(octave_idx_type i = 0 ; i < keys.length(); i++) {
+         boost::python::object py_val;
+
+         octvalue_to_pyobj(py_val, map.contents(keys[i]));
+
+         py_object[keys[i]] = py_val;
+      }
+   }
+
    void octvalue_to_pyobj(boost::python::object &py_object,
                           const octave_value& octvalue) {
-      if (octvalue.is_scalar_type()) {
+      if (octvalue.is_undefined())
+         throw value_convert_exception(
+            "Octave value `undefined'. Can not convert to a Python object");
+      else if (octvalue.is_scalar_type()) {
          if (octvalue.is_bool_type())
             py_object = object(octvalue.bool_value());
          else if (octvalue.is_real_scalar())
@@ -262,14 +302,18 @@
          else
             throw value_convert_exception(
                "Conversion for this scalar not implemented");
-      } else if (octvalue.is_string())
+      } else if (octvalue.is_string()) {
+         if (octvalue.all_strings().dim1() > 1)
+            throw value_convert_exception(
+               "Multi-row character matrices can not be converted.");
          py_object = str(octvalue.string_value());
-      else if (octvalue.is_matrix_type())
+      } else if (octvalue.is_matrix_type()) {
          octvalue_to_pyarr(py_object, octvalue);
-      else if (octvalue.is_undefined())
-         throw value_convert_exception(
-            "Octave value `undefined'. Can not convert to a Python object");
-      else
+      } else if (octvalue.is_map()) {
+         octmap_to_pyobject(py_object, octvalue.map_value());
+      } else if (octvalue.is_cell()) {
+         octcell_to_pyobject(py_object, octvalue.cell_value()); 
+      } else
          throw value_convert_exception(
             "Conversion from Octave value not implemented");
    }
--- a/octave_to_python.h	Mon Nov 17 12:19:57 2008 +0100
+++ b/octave_to_python.h	Tue May 05 21:11:40 2009 +0200
@@ -20,9 +20,6 @@
 #ifndef OCTAVE_TO_PYTHON_H
 #define OCTAVE_TO_PYTHON_H
 
-class octave_value_list;
-class boost::python::tuple;
-
 namespace pytave {
    void octlist_to_pytuple(boost::python::tuple &python_tuple,
                            const octave_value_list &octave_list);
--- a/package/pytave.py	Mon Nov 17 12:19:57 2008 +0100
+++ b/package/pytave.py	Tue May 05 21:11:40 2009 +0200
@@ -50,6 +50,8 @@
 		int (32-bit)        int32
 		float (64-bit)      double
 		str                 string
+		dict                struct
+		list                cell
 		
 	Numeric Array:
 		UBYTE, SBYTE,       matrix of correct type
@@ -67,8 +69,13 @@
 	Scalar values to objects:
 		bool                bool
 		real scalar         float (64-bit)
-		string, sq_string   str
-		str                 string
+		any string*         str
+		struct              dict
+		cell*               list
+
+		* Cell arrays must be one-dimensional (row vector) and
+                  character matrices must only have one row.  Any
+                  other form will raise a ValueConvertError.
 		
 	Matrix values to Numeric arrays:
 		int64               LONG
@@ -106,6 +113,6 @@
 #	fill-column:70
 #	coding:utf-8
 #	indent-tabs-mode:t
-#	tab-width:3
+#	tab-width:8
 #	End:
 # vim: set textwidth=70 noexpandtab tabstop=3 :
--- a/pytave.cc	Mon Nov 17 12:19:57 2008 +0100
+++ b/pytave.cc	Tue May 05 21:11:40 2009 +0200
@@ -55,8 +55,11 @@
 
       // Initialize Octave.
       // Also print Octave startup message.
-      char* argv[] = {"octave", "--no-line-editing", "--no-history", NULL};
-      octave_main(3, argv, 1);
+      const char* argv[] = {"octave",
+                            "--no-line-editing",
+                            "--no-history",
+                            NULL};
+      octave_main(3, const_cast<char**>(argv), 1);
 
       // Initialize Python Numeric Array
 
@@ -112,8 +115,8 @@
                // The struct element is called "stack" but only contain
                // info about the top frame.
                Octave_map stack = stackCell(0).map_value();
-               string file = stack.stringfield("file", "d");
-               string name = stack.stringfield("name", "a");
+               string file = stack.stringfield("file", "");
+               string name = stack.stringfield("name", "");
                int line = stack.intfield("line", 1);
                int column = stack.intfield("column", 2);
 
--- a/python_to_octave.cc	Mon Nov 17 12:19:57 2008 +0100
+++ b/python_to_octave.cc	Tue May 05 21:11:40 2009 +0200
@@ -23,6 +23,8 @@
 #include "arrayobjectdefs.h"
 #undef HAVE_STAT /* both boost.python and octave defines HAVE_STAT... */
 #include <octave/oct.h>
+#include <octave/oct-map.h>
+#include <octave/Cell.h>
 #include <octave/Matrix.h>
 #include <octave/ov.h>
 
@@ -34,6 +36,9 @@
 
 namespace pytave {
 
+   void pyobj_to_octvalue(octave_value &oct_value,
+                          const boost::python::object &py_object);
+
    template <class PythonPrimitive, class OctaveBase>
    static void copy_pyarrobj_to_octarray(OctaveBase &matrix,
                                   const PyArrayObject* const pyarr,
@@ -107,10 +112,9 @@
    }
 
    static void pyarr_to_octvalue(octave_value &octvalue,
-                          const PyArrayObject *pyarr) {
+                                 const PyArrayObject *pyarr) {
       if (pyarr->nd < 1)
          throw object_convert_exception("Less than 1 dimensions not supported");
-
       dim_vector dims;
       switch (pyarr->nd) {
          case 1:
@@ -182,12 +186,127 @@
       }
    }
 
+   static void pylist_to_cellarray(octave_value &oct_value,
+                                   const boost::python::list &list) {
+
+      octave_idx_type length = boost::python::extract<octave_idx_type>(
+         list.attr("__len__")());
+      octave_value_list values;
+
+      for(octave_idx_type i = 0; i < length; i++) {
+         octave_value val;
+
+         pyobj_to_octvalue(val, list[i]);
+         values.append(val);
+
+      }
+
+      oct_value = Cell(values);
+   }
+
+   static void pydict_to_octmap(octave_value &oct_value,
+                                const boost::python::dict &dict) {
+
+      boost::python::list list = dict.items();
+      octave_idx_type length = boost::python::extract<octave_idx_type>(
+         list.attr("__len__")());
+
+      dim_vector dims = dim_vector(1, 1);
+
+      bool has_dimensions = false;
+
+      for(octave_idx_type i = 0; i < length; i++) {
+         octave_value val;
+
+         boost::python::tuple tuple =
+            boost::python::extract<boost::python::tuple>(list[i])();
+
+         pyobj_to_octvalue(val, tuple[1]);
+
+         if(val.is_cell()) {
+            const Cell c(val.cell_value());
+            if (error_state)
+               throw object_convert_exception("Octave error");
+
+            // Some things are assumed since we have converted a Python list to
+            // a cell.
+            assert(c.dims().length() == 2);
+            assert(c.dim1() == 1);
+
+            // We do not bother measuring 1x1 values, since they are replicated
+            // to fill up the necessary dimensions.
+            if(!(c.dims().length() == 2 && c.dims()(0) == 1 && c.dims()(1) == 1)) {
+
+               if(!has_dimensions) {
+                  dims = c.dims();
+                  has_dimensions = true;
+               } else if(c.dims() != dims) {
+                  throw object_convert_exception(
+                     "Dimensions of the struct fields do not match");
+               }
+            }
+         }
+      }
+
+      Octave_map map = Octave_map(dims);
+
+      for(octave_idx_type i = 0; i < length; i++) {
+         octave_value val;
+         std::string key;
+
+         boost::python::tuple tuple =
+            boost::python::extract<boost::python::tuple>(list[i])();
+
+         boost::python::extract<std::string> str(tuple[0]);
+         if(!str.check()) {
+            throw object_convert_exception(
+               string("Can not convert key of type ")
+               + PyEval_GetFuncName(boost::python::object(tuple[0]).ptr())
+               + PyEval_GetFuncDesc(boost::python::object(tuple[0]).ptr())
+               + " to a structure field name. Field names must be strings.");
+         }
+
+         key = str();
+
+         if (!valid_identifier(key)) {
+            throw object_convert_exception(
+               string("Can not convert key `") + key + "' to a structure "
+               "field name. Field names must be valid Octave identifiers.");
+         }
+
+         // FIXME: Second time around we convert exactly the same object
+         pyobj_to_octvalue(val, tuple[1]);
+
+         if(!val.is_cell()) {
+            map.assign(key, Cell(dims, val));
+         } else {
+            const Cell c(val.cell_value());
+
+            if (error_state)
+               throw object_convert_exception("Octave error");
+
+            if(c.dims().length() == 2 && c.dims()(0) == 1 && c.dims()(1) == 1) {
+               map.assign(key, Cell(dims, c(0)));
+            }
+            else {
+               map.assign(key, c);
+            }
+         }
+         if (error_state) {
+            throw object_convert_exception("Octave error");
+         }
+      }
+      oct_value = map;
+    }
+
    void pyobj_to_octvalue(octave_value &oct_value,
                           const boost::python::object &py_object) {
       extract<int> intx(py_object);
       extract<double> doublex(py_object);
       extract<string> stringx(py_object);
       extract<numeric::array> arrayx(py_object);
+      extract<boost::python::list> listx(py_object);
+      extract<boost::python::dict> dictx(py_object);
       if (intx.check()) {
          oct_value = intx();
       } else if (doublex.check()) {
@@ -196,6 +315,10 @@
          pyarr_to_octvalue(oct_value, (PyArrayObject*)py_object.ptr());
       } else if (stringx.check()) {
          oct_value = stringx();
+      } else if (listx.check()) {
+         pylist_to_cellarray(oct_value, (boost::python::list&)py_object);
+      } else if (dictx.check()) {
+         pydict_to_octmap(oct_value, (boost::python::dict&)py_object);
       } else {
          throw object_convert_exception(
             PyEval_GetFuncName(py_object.ptr())
@@ -213,8 +336,6 @@
          pyobj_to_octvalue(octave_list(i), python_tuple[i]);
       }
    }
-
-
 }
 
 /* Emacs
--- a/python_to_octave.h	Mon Nov 17 12:19:57 2008 +0100
+++ b/python_to_octave.h	Tue May 05 21:11:40 2009 +0200
@@ -20,9 +20,6 @@
 #ifndef PYTHON_TO_OCTAVE_H
 #define PYTHON_TO_OCTAVE_H
 
-class octave_value_list;
-class boost::python::tuple;
-
 namespace pytave {
    void pytuple_to_octlist(octave_value_list &octave_list,
                            const boost::python::tuple &python_tuple);
--- a/setup.py.in	Mon Nov 17 12:19:57 2008 +0100
+++ b/setup.py.in	Tue May 05 21:11:40 2009 +0200
@@ -31,9 +31,9 @@
          
          # TODO: Check whether paths work on Windows or not.
          # The file separator might be wrong. (Must be / in setup.cfg)
-         include_dirs = ['@PYTAVE_OCTAVE_INCLUDE_PATH@', '@abs_builddir@', '@srcdir@'], # Python always included.
+         include_dirs = ['@OCTAVE_INCLUDEDIR@', '@abs_builddir@', '@srcdir@'], # Python always included.
          define_macros = [('HAVE_CONFIG_H', '1')],
-         library_dirs = ['@PYTAVE_OCTAVE_RPATH@'],
+         library_dirs = ['@OCTAVE_LIBRARYDIR@'],
          runtime_library_dirs = ['@PYTAVE_OCTAVE_RPATH@'],
          libraries = ['octinterp', 'octave', 'cruft', '@BOOST_PYTHON_LIB@']
       )
--- a/test/test.py	Mon Nov 17 12:19:57 2008 +0100
+++ b/test/test.py	Tue May 05 21:11:40 2009 +0200
@@ -1,89 +1,203 @@
 #!/usr/bin/python
+# -*- coding:utf-8 -*-
 
 import pytave
 import Numeric
 
-pytave.feval(0, "addpath", ".",);
+print "No messages indicates test pass."
 
 arr0_0 = Numeric.zeros((0,0));
 arr0_1 = Numeric.zeros((0,1));
 arr1_0 = Numeric.zeros((1,0));
-arr1f = Numeric.array([1, 2, 3, 4], Numeric.Float32)
-arr1b = Numeric.array([1, 2, 3, 256], Numeric.Int8)
-arr1i = Numeric.array([1, 2, 3, 4], Numeric.Int)
-arr1i32 = Numeric.array([1, 2, 3, 4], Numeric.Int32)
-arr1a = Numeric.array([1, 2, 3, 4])
-arr2f = Numeric.array([[1, 2, 3, 4],[5,6,7,8]], Numeric.Float32)
-arr2d = Numeric.array([[1, 2, 3, 4],[5,6,7,8]], Numeric.Float)
-arr3f = Numeric.array([[[1, 2, 3, 4],[5,6,7,8]],[[9, 10, 11, 12],[13,14,15,16]]], Numeric.Float32)
+number = Numeric.array([1.32], Numeric.Float32)
+arr1fT = Numeric.array([[1.32], [2], [3], [4]], Numeric.Float32)
+arr1fT2 = Numeric.array([[1.32, 2, 3, 4]], Numeric.Float32)
+arr1f = Numeric.array([[1.32, 2, 3, 4]], Numeric.Float32)
+arr1b = Numeric.array([[8, 2, 3, 256]], Numeric.Int8)
+arr1i = Numeric.array([[17, 2, 3, 4]], Numeric.Int)
+arr1i32 = Numeric.array([[32, 2, 3, 4]], Numeric.Int32)
+arr1a = Numeric.array([[1, 2, 3, 4]])
+arr2f = Numeric.array([[1.32, 2, 3, 4],[5,6,7,8]], Numeric.Float32)
+arr2d = Numeric.array([[1.17, 2, 3, 4],[5,6,7,8]], Numeric.Float)
+arr3f = Numeric.array([[[1.32, 2, 3, 4],[5,6,7,8]],[[9, 10, 11, 12],[13,14,15,16]]], Numeric.Float32)
 
-alimit_int32 = Numeric.array([-2147483648, 2147483647], Numeric.Int32);
-alimit_int16 = Numeric.array([-32768, 32767, -32769, 32768], Numeric.Int16);
-alimit_int8 = Numeric.array([-128, 127, -129, 128], Numeric.Int8);
-alimit_uint8 = Numeric.array([0, 255, -1, 256], Numeric.UnsignedInt8);
+alimit_int32 = Numeric.array([[-2147483648, 2147483647]], Numeric.Int32);
+alimit_int16 = Numeric.array([[-32768, 32767, -32769, 32768]], Numeric.Int16);
+alimit_int8 = Numeric.array([[-128, 127, -129, 128]], Numeric.Int8);
+alimit_uint8 = Numeric.array([[0, 255, -1, 256]], Numeric.UnsignedInt8);
 
 
-b = pytave.feval(1, "testfile", 1)
-print "first exec ok:", b
+# This eval call is not to be seen as a encouragement to use Pytave
+# like this. Create a separate .m-file with your complex Octave code.
+pytave.feval(1, "eval", "function [result] = test_return(arg) "
+"result = arg; endfunction")
+
+pytave.feval(1, "test_return", 1)
 
 def testequal(value):
 	try:
-		print "------------ test ", value
-		nvalue = pytave.feval(1, "testfile", *value)
+		nvalue, = pytave.feval(1, "test_return", value)
 		if nvalue != value:
-			print "Equal ", value, " == ", nvalue, ", ", (nvalue == value), " Equal"
+			print "FAIL as ", value, " != ", nvalue
+	except TypeError, e:
+		print "FAIL: ", value,":", e
+
+def testexpect(value, expected):
+	try:
+		nvalue, = pytave.feval(1, "test_return", value)
+		if nvalue != expected:
+			print "FAIL as ", nvalue, " != ", expected, ","
+			print "        sent in", value
+	except TypeError, e:
+		print "FAIL: ", value,":", e
+
+
+def testmatrix(value):
+	try:
+		nvalue, = pytave.feval(1, "test_return", value)
+#		print "test", (value,)
+#		print "returned ", (nvalue,)
+		class1 = pytave.feval(1, "class", value)
+		class2 = pytave.feval(1, "class", nvalue)
+		if nvalue != value:
+			print "FAIL as ", value, " != ", nvalue
+		if value.shape != nvalue.shape:
+			print "Size check failed for: ", (value,) ,". Got ",value.shape, "and later", nvalue.shape, " =++ ", (nvalue,)
+		if class1 != class2:
+			print "Type check failed for: ", (value,) ,". Got ",class1, "and later", class2
 	except TypeError, e:
 		print "Execute failed: ", value,":", e
 
-def testint(value):
+def testobjecterror(value):
+	try:
+		print pytave.feval(1, "test_return", value);
+		print "FAIL:", (value,)
+	except pytave.ObjectConvertError:
+		pass
+	except Exception, e:
+		print "FAIL", (value,), e
+
+def testvalueerror(*value):
+	try:
+		print pytave.feval(1, *value);
+		print "FAIL:", (value,)
+	except pytave.ValueConvertError:
+		pass
+	except Exception, e:
+		print "FAIL", (value,), e
+
+def testvalueok(*value):
 	try:
-		print "------------ int test ", value
-		nvalue = pytave.feval(1, "testfile", *value)
-		class1 = pytave.feval(1, "class", *value)
-		class2 = pytave.feval(1, "class", *nvalue)
-		if class1 != class2:
-			print "Integer check failed, got ",class1, "and later", class2
-	except TypeError, e:
-		print "Execute failed: ", value,":", e
-	
-print "------------"
+		pytave.feval(1, *value);
+	except Exception, e:
+		print "FAIL", (value,), e
+
+def testcellinvariant(value):
+	pass
+
+testequal('a')
+
+
+testmatrix(alimit_int32)
+testmatrix(alimit_int16)
+testmatrix(alimit_int8)
+
+# Strings
+# Multi-row character matrix cannot be returned
+testvalueerror("eval", "['foo'; 'bar']")
+testequal('a')
 
-testint((alimit_int32, ))
-testint((alimit_int16, ))
-testint((alimit_int8, ))
+testequal("mystring")
+testequal('mystring')
+testequal("mystringåäöÅÄÖ")
+
+testequal(1)
+testequal(1L)
+testequal(1.2)
+testequal(1.2)
 
-testequal((alimit_int32, ))
-testequal((alimit_int16, ))
-testequal((alimit_int8, ))
+# Vector arrays
+testmatrix(arr1a)
+testmatrix(arr1f)
+testmatrix(arr1fT)
+testmatrix(arr1fT2)
+testmatrix(arr1i)
+testmatrix(arr1b)
+testmatrix(arr1i32)
 
-testequal(("mystring", ))
+# 2d arrays
+testmatrix(arr2f)
+testmatrix(arr2d)
+
+# 3d arrays
+testmatrix(arr3f)
 
-testequal((1, ))
-testequal((1L, ))
-testequal((1.2, ))
-testequal((1.2, ))
-testequal((arr1a, ))
+# Note, both arr0_0 == arr0_0 and arr0_0 != arr0_0 are false!
+if (arr0_0 != arr0_0) or (arr0_0 == arr0_0):
+	print "FAIL: Zero test", 
+
+testmatrix(arr0_0)
+testmatrix(arr1_0)
+testmatrix(arr0_1)
+
+# Lists
+testequal([1, 2])
+testequal([[1, 2], [3, 4]])
+testequal([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
+testequal([])
 
-testequal((arr1f, ))
-testequal((arr1i, ))
-testequal((arr1b, ))
-testequal((arr1i32, ))
-testequal((arr2f, ))
-testequal((arr2d, ))
+# Return cells with OK dimensions
+testvalueok("cell", 1, 3);
+testvalueok("cell", 1, 0)
+
+# Return cells with incompatible dimensions
+testvalueerror("cell", 3, 1)
+testvalueerror("cell", 0, 0)
+testvalueerror("cell", 0, 1)
 
-testequal((arr3f, ))
+# Dictionaries
+
+# Simple dictionary tests
+testequal({"foo": [1], "bar": [2]})
+testequal({"x": [1, 3], "y": [2, 4]})
+testequal({"x": [1, "baz"], "y": [2, "foobar"]})
+testequal({"x": [arr1f], "y": [arr1i]})
+testequal({})
 
-print("Equality for these three tests fails")
-testequal((arr0_0, ))
-testequal((arr1_0, ))
-testequal((arr0_1, ))
+# Try some odd dictionaries
+# The implicit conversion makes Pytave return cell-wrapped results.
+testexpect({"foo": number,   "bar": 2},
+	   {"foo": [number], "bar": [2]})
+testexpect({"foo": arr1f,    "bar": arr2f},
+	   {"foo": [arr1f],  "bar": [arr2f]})
+testexpect({"foo": 1,        "bar": 2},
+	   {"foo": [1],      "bar": [2]})
+testexpect({"foo": 1,        "bar": [2]},
+	   {"foo": [1],      "bar": [2]})
+testexpect({"foo": 1,        "bar": [2, 3]},
+	   {"foo": [1, 1],   "bar": [2, 3]})
+testexpect({"foo": [1],      "bar": [2, 4]},
+	   {"foo": [1, 1],   "bar": [2, 4]})
+testexpect({"bar": 1,        "foo": [2, 3]},
+	   {"bar": [1, 1],   "foo": [2, 3]})
+testexpect({"bar": [1],      "foo": [2, 4]},
+	   {"bar": [1, 1],   "foo": [2, 4]})
 
-# these should fail.
-print("These tests should fail.")
-testequal(([1, 2],))
-testequal((None,))
-testequal(((1,),))
-testequal(([],))
-testequal(((),))
-testequal((1, 8.9, 3, 4, "testfile", [], arr1f))
+# Try some invalid keys
+testobjecterror({"this is not an Octave identifier": 1})
+testobjecterror({1.22: 1})
+
+# These should fail: No object conversion defined.
+testobjecterror(None)
+testobjecterror((1, ))
+testobjecterror(())
 
+result, = pytave.feval(1, "eval", "[1, 1, 1]")
+if result.shape != (1, 3):
+	print "FAIL: expected 1x3 matrix"
+
+result, = pytave.feval(1, "eval", "[1; 2; 3]");
+if result.shape != (3, 1):
+	print "FAIL: expected 3x1 matrix"
+
+
--- a/testfile.m	Mon Nov 17 12:19:57 2008 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,5 +0,0 @@
-function [testresult] = testfile(arg)
-	 disp(arg)
-	 disp(["Type info: " typeinfo(arg)])
-	 testresult = arg;#int8([1]);
-end