C arrays solution (was: Re: [C++-sig] Re: IntWrapper.hpp in indexing_suite)

Niall Douglas s_sourceforge at nedprod.com
Mon Oct 13 04:33:34 CEST 2003


On 12 Oct 2003 at 18:05, Raoul Gough wrote:

> > The below works lovely, and my thanks for the advice. The problem
> > was the boost::noncopyable in the MyListCArray declaration.
> 
> I wouldn't have guessed that it had to do with the noncopyable, so I
> don't think I actually helped out at all. Still, a good result in the
> end :-)

Well I had reached that point of despair when you just stare at the 
code and hope something comes to you. That did, and hey presto!

> > Ok, next question: How do you determine the return type of a
> > function pointer? It must be possible as bpl determines return type
> > in def() - get_signature() from signature.hpp looked hopeful, but it
> > appears to be a run-time not compile-time function.
> 
> Not sure if this is how Boost.Python does it, but the Boost
> type_traits library would be sufficient for what you described
> above. See the "Function Traits" section of libs/type_traits/index.htm
> for details.

Actually this came to me as a sort of epiphany today as I was hauling 
rigging off a boat - some number of hours later and I have the below, 
the very first working proof of concept.

I should also add that the below is my VERY FIRST C++ metaprogram. I 
failed a job interview for not knowing it, bought Andrei's Modern C++ 
Design immediately afterwards and have been playing with it on & off 
since for the last four months. But not until today did I actually 
ever write something on my own bat not copied from elsewhere. I feel 
like my very first 1000 line program in BBC Basic nearly two decades 
ago now!

Note the below is nasty (especially my choice of non-distinctive 
naming) and only supports one instance currently. I'm going to need a 
functor more generic than the boost one in order to store a hash 
table of functions from which I can correctly invoke translation (you 
can see the hack I used below to access the function pointers). Thus 
chances are that my end effort will be compatible with my library, 
but not yours.

Thoughts on the below? Is it worth you integrating similar 
functionality and thus all other bpl users can use it? Or is this too 
esoteric and/or demanding to warrant inclusion?

Cheers,
Niall

--- cut ---
#include <boost/python.hpp>
#include <boost/python/suite/indexing/container_suite.hpp>
#include <boost/python/suite/indexing/iterator_pair.hpp>
#include <boost/python/suite/indexing/container_proxy.hpp>
#include <string>

class MyList
{
	std::string *array;
public:
	MyList();
	std::string *getData() { return array; }
	int getDataLen() const { return 4; }
};

MyList::MyList()
{
	static std::string data[]={ std::string("Niall"),
								std::string("is"),
								std::string("a"),
								std::string("teapot")
								};
	array=data;
}

// ****** Where the CArray.h stuff begins ********

static void *carray;
template<typename getArrayFn, typename getLenFn> class CArray
{
	// Gets the return type of getArrayFn
	template<typename fn> struct fnInfo;
	template<typename R, typename O> struct fnInfo<R (O::*)()>
	{
		typedef R resultType;
		typedef O objectType;
	};
	typedef typename fnInfo<getArrayFn> arrayFnInfo;
	typedef typename arrayFnInfo::resultType arrayType;
	// Sets subType::value to the type of the array's contents (ie; 
arrayType less an indirection level)
	template<class sT> struct subType;
	template<class sT> struct subType<sT *>
	{
		typedef sT value;
	};
	getArrayFn getArrayFunc;	// Gets the array data
	getLenFn getLenFunc;		// Gets the length of the array data
public:
	//! The type of the container
	typedef typename arrayFnInfo::objectType container;
	//! The type the array contains
	typedef typename subType<arrayType>::value memberType;
	//! Type used to access array (and sets its upper and lower members)
	typedef boost::python::indexing::iterator_pair<memberType *> 
mTypeIt;

	//! Constructor
	CArray(getArrayFn _getArrayFunc, getLenFn _getLenFunc)
		: getArrayFunc(_getArrayFunc), getLenFunc(_getLenFunc)
	{
		boost::python::class_<mTypeIt>("CArray_unique", 
			boost::python::init<memberType *, memberType *>())
			.def(boost::python::indexing::container_suite<mTypeIt>());
	}
	//! Returns an appropriately wrapped array
	static typename mTypeIt getArray(container &l)
	{
		CArray<getArrayFn, getLenFn> *that=(CArray<getArrayFn, getLenFn> *) 
carray;		// Temporary
		memberType *data=(l.*that->getArrayFunc)();
		return mTypeIt(data, data+(l.*that->getLenFunc)());
	}
	//! A type representing the getArray function above
	typedef typename mTypeIt (*getArrayFunctionType)(container &);
};


template<typename getArrayFn, typename getLenFn> typename 
CArray<getArrayFn, getLenFn>::getArrayFunctionType 
MakeCArray(getArrayFn a, getLenFn b)
{
	carray=(void *) new CArray<getArrayFn, getLenFn>(a, b);
	return &CArray<getArrayFn, getLenFn>::getArray;
}

BOOST_PYTHON_MODULE(TestCArrays)
{
    boost::python::class_< MyList, boost::noncopyable >("MyList")
		.def("getData", MakeCArray(&MyList::getData, &MyList::getDataLen))
	;
}





-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 208 bytes
Desc: not available
URL: <http://mail.python.org/pipermail/cplusplus-sig/attachments/20031013/283d8ae0/attachment.pgp>


More information about the Cplusplus-sig mailing list