Skip to content

Commit

Permalink
Add CallMethod structs for 2 arguments Refs #970
Browse files Browse the repository at this point in the history
Copy-and-paste needs tidying up
  • Loading branch information
martyngigg committed Apr 15, 2013
1 parent dfdcc85 commit 47915c8
Show file tree
Hide file tree
Showing 3 changed files with 138 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
#include <boost/python/class.hpp>
#include <boost/python/call_method.hpp>


namespace Mantid { namespace PythonInterface {
namespace Environment
{
Expand All @@ -45,7 +44,7 @@ namespace Mantid { namespace PythonInterface {
* Perform a call to a python function that takes no arguments and returns a value
*/
template<typename ResultType>
struct DLLExport CallMethod_NoArg
struct DLLExport CallMethod0
{
/**
* Dispatch a call to the method on the given object. If the method does not exist
Expand Down Expand Up @@ -107,7 +106,7 @@ namespace Mantid { namespace PythonInterface {

///Specialization for void return type
template<>
struct DLLExport CallMethod_NoArg<void>
struct DLLExport CallMethod0<void>
{
/**
* Dispatch a call to the method on the given object. If the method does not exist
Expand Down Expand Up @@ -164,6 +163,134 @@ namespace Mantid { namespace PythonInterface {
};
//@}

/** @name Two argument Python calls */
//@{
/**
* Perform a call to a python function that takes no arguments and returns a value
*/
template<typename ResultType,typename Arg1,typename Arg2>
struct DLLExport CallMethod2
{
/**
* Dispatch a call to the method on the given object. If the method does not exist
* then return the defaultValue
* @param self :: The object containing the method definition
* @param funcName :: The method name
* @param defaultValue :: A default value if the method does not exist
* @return The value of the function or the default value if it does not exist
*/
static ResultType dispatchWithDefaultReturn(PyObject *self, const char * funcName, const ResultType & defaultValue,
const Arg1 & arg1, const Arg2 & arg2)
{
GlobalInterpreterLock gil;
if(Environment::typeHasAttribute(self, funcName))
{
try
{
return boost::python::call_method<ResultType,Arg1,Arg2>(self, funcName,arg1,arg2);
}
catch(boost::python::error_already_set&)
{
translateErrorToException();
}
}
return defaultValue;
}

/**
* Dispatch a call to the method on the given object. If the method does not exist
* then raise a std::runtime_error exception
* @param self :: The object containing the method definition
* @param funcName :: The method name
* @param errorMsg :: An error message to pass to the generated exception
* @return The value of the function or the default value if it does not exist
*/
static ResultType dispatchWithException(PyObject *self, const char * funcName)
{
GlobalInterpreterLock gil;
if(Environment::typeHasAttribute(self, funcName))
{
try
{
return boost::python::call_method<ResultType>(self, funcName);
}
catch(boost::python::error_already_set&)
{
translateErrorToException();
}
}
else
{
std::ostringstream os;
os << self->ob_type->tp_name << " has no function named '" << funcName << "'\n"
<< "Check the function exists and that its first argument is self.";
throw std::runtime_error(os.str());
}
return ResultType();
}
};

///Specialization for void return type
template<typename Arg1,typename Arg2>
struct DLLExport CallMethod2<void,Arg1,Arg2>
{
/**
* Dispatch a call to the method on the given object. If the method does not exist
* then do nothing
* @param self :: The object containing the method definition
* @param funcName :: The method name
* @return The value of the function or the default value if it does not exist
*/
static void dispatchWithDefaultReturn(PyObject *self, const char * funcName,
const Arg1 & arg1, const Arg2 & arg2)
{
GlobalInterpreterLock gil;
if(Environment::typeHasAttribute(self, funcName))
{
try
{
boost::python::call_method<void,Arg1,Arg2>(self, funcName,arg1,arg2);
}
catch(boost::python::error_already_set&)
{
translateErrorToException();
}
}
}
/**
* Dispatch a call to the method on the given object. If the method does not exist
* then raise a runtime_error
* @param self :: The object containing the method definition
* @param funcName :: The method name
* @param errorMsg :: An error message if the method does not exist
* @return The value of the function or the default value if it does not exist
*/
static void dispatchWithException(PyObject *self, const char * funcName,
const Arg1 & arg1, const Arg2 & arg2)
{
GlobalInterpreterLock gil;
if(Environment::typeHasAttribute(self, funcName))
{
try
{
boost::python::call_method<void,Arg1,Arg2>(self, funcName,arg1,arg2);
}
catch(boost::python::error_already_set&)
{
translateErrorToException();
}
}
else
{
std::ostringstream os;
os << self->ob_type->tp_name << " has no function named '" << funcName << "'\n"
<< "Check the function exists and that its first argument is self.";
throw std::runtime_error(os.str());
}
}
};
//@}

}
}}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
#include "MantidPythonInterface/api/FitFunctions/IFunction1DAdapter.h"

#include "MantidPythonInterface/kernel/Converters/WrapWithNumpy.h"
#include "MantidPythonInterface/kernel/Environment/CallMethod.h"
#include "MantidPythonInterface/kernel/Environment/WrapperHelpers.h"

#include <boost/python/call_method.hpp>
#include <boost/python/class.hpp>

//-----------------------------------------------------------------------------
Expand All @@ -13,9 +13,9 @@ namespace Mantid
{
namespace PythonInterface
{
using Environment::CallMethod2;
using namespace boost::python;


/**
* Construct the "wrapper" and stores the reference to the PyObject
* * @param self A reference to the calling Python object
Expand Down Expand Up @@ -54,7 +54,7 @@ namespace Mantid
*/
void IFunction1DAdapter::function1D(boost::python::object & out, const boost::python::object & xvals) const
{
boost::python::call_method<void,object,object>(getSelf(), "function1D", out, xvals);
CallMethod2<void,object,object>::dispatchWithException(getSelf(), "function1D", out, xvals);
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace Mantid
namespace PythonInterface
{
using namespace boost::python;
using Environment::CallMethod_NoArg;
using Environment::CallMethod0;

/**
* Construct the "wrapper" and stores the reference to the PyObject
Expand All @@ -37,7 +37,7 @@ namespace Mantid
*/
int AlgorithmWrapper::version() const
{
return CallMethod_NoArg<int>::dispatchWithDefaultReturn(getSelf(), "version", defaultVersion());
return CallMethod0<int>::dispatchWithDefaultReturn(getSelf(), "version", defaultVersion());
}

int AlgorithmWrapper::defaultVersion() const
Expand All @@ -51,7 +51,7 @@ namespace Mantid
*/
const std::string AlgorithmWrapper::category() const
{
return CallMethod_NoArg<std::string>::dispatchWithDefaultReturn(getSelf(), "category", defaultCategory());
return CallMethod0<std::string>::dispatchWithDefaultReturn(getSelf(), "category", defaultCategory());
}

/**
Expand All @@ -69,7 +69,7 @@ namespace Mantid
*/
void AlgorithmWrapper::init()
{
CallMethod_NoArg<void>::dispatchWithException(getSelf(), "PyInit");
CallMethod0<void>::dispatchWithException(getSelf(), "PyInit");
}

/**
Expand All @@ -79,7 +79,7 @@ namespace Mantid
void AlgorithmWrapper::exec()
{

CallMethod_NoArg<void>::dispatchWithException(getSelf(), "PyExec");
CallMethod0<void>::dispatchWithException(getSelf(), "PyExec");
}

}
Expand Down

0 comments on commit 47915c8

Please sign in to comment.