Boost logo

Boost :

From: John Barnard (barnard_at_[hidden])
Date: 2000-12-11 11:52:12


Before I ask my question about BPL, let me thank David, Ullrich, and
all of the contributors and testers of BPL. I've been very impressed
with it in the short time of being using it. I've tried SWIG and CXX,
but neither allowed be to use the full range of C++ features via
Python.

Now on to my question/problem: I'm trying to pass an Python subclass
instance of a C++ abstract class back to C++. I have a Python class
testPI which is a subclass of the wrapped C++ abstract class LogPI. I
wish to pass an instance of testPI to a method draw of the wrapped C++
class StochasticGrid (all of this in Python, of course), where the
method draw expects a reference to a LogPI object. When I attempt to
this I get the error message:

RuntimeError: __init__ function for extension class 'LogPI' was never
called.

indicating the BPL was expecting a constructor for the abstract class
LogPI. Can you do this in BPL or have I made an error. I've attached
the relevant C++ and Python code below. I'm using Microsoft VC++ with
the latest patches on MS 98SE.

Thanks,

John


#ifndef SGRID_PYTHON_INTERFACE_H
#define SGRID_PYTHON_INTERFACE_H

#include <boost/python/class_builder.hpp>
#include <boost/python/callback.hpp>
#include <boost/utility.hpp>
#include "LogPI.h"
#include "StochasticGrid.h"
#include "CRobLib.h"

namespace grid_python {

  using SGrid::StochasticGrid;
  using SGrid::CRobLib;

  double get_SG_draw(const StochasticGrid& grid, CRobLib& gen) {
    return grid.draw(gen);
  };

  class LogPI_callback : LogPI {
  public:
    double logP(double x) {
      boost::python::callback<double>::call_method(m_self, "logP", x);
    }
    
  private:
    PyObject* m_self;
  }; // class LogPI_callback

} // namespace grid_python

#endif // SGRID_PYTHON_INTERFACE_H





#include "grid_python_interface.h"
#include <boost/python/class_builder.hpp>
#include <boost/python/callback.hpp>
#include <boost/utility.hpp>
#include <stdio.h>

// Python requires an exported function called init<module-name> in every
// extension module. This is where we build the module contents.
extern "C"
#ifdef _WIN32
__declspec(dllexport)
#endif
void initgrid()
{
  try
    {
      // create an object representing this extension module
      boost::python::module_builder grid("grid");
      
      // Create the Python type object for our extension class
      boost::python::class_builder<SGrid::CRobLib> CRobLibPC(grid, "CRobLib");
      
      // Add the __init__ function
      CRobLibPC.def(boost::python::constructor<long>());
      CRobLibPC.def(boost::python::constructor<>());
      // Add a regular member function
      CRobLibPC.def(&SGrid::CRobLib::nextDouble, "nextDouble");
      CRobLibPC.def(&SGrid::CRobLib::nextGaussian, "nextGaussian");

      // Create the Python type object for our extension class
      boost::python::class_builder<SGrid::PdPair> PdPairPC(grid, "PdPair");

      // Add the __init__ function
      PdPairPC.def(boost::python::constructor<>());

      // Create the Python type object for our extension class
      boost::python::class_builder<LogPI,grid_python::LogPI_callback>
        LogPIPC(grid, "LogPI");

      // Add a pure virtual function
      LogPIPC.def(&LogPI::logP, "logP");
      
      // Create the Python type object for our extension class
      boost::python::class_builder<SGrid::StochasticGrid>
        StochasticGridPC(grid, "StochasticGrid");
      
      // Add the __init__ function
      StochasticGridPC.def(boost::python::constructor<LogPI&,double,double,int>());

      // Add a regular member function
      // StochasticGridPC.def((double (SGrid::StochasticGrid::*)(const CRobLib&)) &SGrid::StochasticGrid::draw, "draw");
      StochasticGridPC.def(grid_python::get_SG_draw, "draw");
      // StochasticGridPC.def((double (SGrid::StochasticGrid::*)(double, const CRobLib&)) &SGrid::StochasticGrid::draw, "draw");

      // Add a regular function to the module
      //grid.def(length, "length");
    }
  catch(...)
    {
      boost::python::handle_exception(); // Deal with the exception for Python
    }
}

#if defined(_WIN32)
# ifdef __MWERKS__
# pragma ANSI_strict off
# endif
# include <windows.h>
# ifdef __MWERKS__
# pragma ANSI_strict reset
# endif
extern "C" BOOL WINAPI DllMain ( HINSTANCE hInst, DWORD wDataSeg, LPVOID lpvReserved );

# ifdef BOOST_MSVC
extern "C" void structured_exception_translator(unsigned int, EXCEPTION_POINTERS*)
{
    throw;
}
# endif

#ifndef NDEBUG
namespace boost { namespace python { namespace detail {
        extern int total_Dispatchers;
}}} // namespace boost::python::detail
#endif

BOOL WINAPI DllMain(
    HINSTANCE, //hDllInst
    DWORD fdwReason,
    LPVOID // lpvReserved
    )
{
# ifdef BOOST_MSVC
    _set_se_translator(structured_exception_translator);
#endif
    (void)fdwReason; // warning suppression.

#ifndef NDEBUG
    switch(fdwReason)
    {
    case DLL_PROCESS_DETACH:
        assert(bpl_test::total_Ints == 0);
    }
#endif
    
    return 1;
}
#endif // _WIN32



#ifndef LOGPI_H
#define LOGPI_H

class LogPI
{
 public:
  virtual double logP(double x) const = 0;
};

#endif // LOGPI_H


#ifndef SGRID_H
#define SGRID_H

#include "LogPI.h"
#include "CRobLib.h"

namespace SGrid {

class PdPair
{
 public:
  double prob;
  int draw;
};

class MidPoints
{
 public:
  int D;
  int U;
};

class DUandPDown
{
 public:
  DUandPDown() {D=0; U=0;}
  ~DUandPDown() {if(D!=0) delete [] D; if(U!=0) delete [] U;}
  int* D;
  int* U;
  double pDown;
};

class StochasticGrid
{
 public:
  //constructors, destructor--------------------
  StochasticGrid(LogPI& logPI, double a, double b, int nGrid);
  ~StochasticGrid();
  //++++++++++++++++++++++++++++++++++++++++++++
  
  //public methods---------------------------------
  double* gridProbs() { return getProbs(1,nGrid);}
  double draw(const CRobLib& gen);
  double draw(double x, const CRobLib& gen);
  //++++++++++++++++++++++++++++++++++++++++++++++++
  
 private:
  // data members------------------------------
  int nGrid; // the grid size
  double a, b; // the grid covers the interval (a,b)
  double width;
  // the discete ith value is x(i) = w(i-.5), where w = (b-a)/nGrid
  // so the x(i) are in the middle of the nGrid segments of length w covering
  // the interval (a,b)
  const LogPI& logPI; // the model giving the log density
  double* w; // the weights for the likelihoods, right and left starting from the middle
  int nw; // number of weights = # of log density evaluations on each side
  double* logP; // this will be of length nGrid, ith value is log density at x(i)
  int* isLogPset; // ith is 1 if ith of logP is set, 0 else
  //++++++++++++++++++++++++++++++++++++++++++
  
  // private methods-----------------------------
  double oneDlogP(double x);
  MidPoints* getMidPoints(int bot, int top);
  double getLogP(int i);
  double* getProbs(int bot, int top);
  PdPair* draw(int bot, int top, const CRobLib& gen);
  DUandPDown* calcPDown(int bot, int top);
  //++++++++++++++++++++++++++++++++++++++++++++++
};

} // namespace SGrid

#endif // SGRID_H


-- 
John Barnard
Assistant Professor
Department of Statistics
Harvard University
Phone: (617) 495-1603
Fax:   (617) 496-8057
Email: barnard_at_[hidden]

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk