Boost logo

Boost :

From: Ullrich Koethe (koethe_at_[hidden])
Date: 2000-10-17 05:13:25


> > Alternatively, If the NTL gives you a C/C++ interface, you can also
> It does -- NTL is a C++ library for unlimited-precision numerics,
> polynomial arithmetic, &c.
>
> > your own converter function:
> >
> > some_ntl_type& from_python(PyObject* p, py::Type<some_NTL_type&>)
> > {
> > // an Example implementation. Basically, you need
> > // to extract the NTL type from the PyObject*.
> > if (p->ob_type != NTL_long_type) {
> > PyErr_SetString(PyExc_TypeErr, "NTL long required");
> > throw py::ArgumentError();
> > }
> > return *static_cast<some_NTL_type*>(p);
> > }
> >
> > then the C++ functions you're wrapping can take a some_NTL_type&
> > parameter directly.
>
> *blink* I must be slow (it's almost midnight here:-) but I don't get it.
>
> How would this help me expose to Python a function, that a Python
> program can call as, say,
> x=MyModule.MyFun(9876229292L)
> and returns an instance of some NTL class I've wrapped...? Thanks
> for any help!

Perhaps I can help clarifying things. There are basically two solutions
to your problem:

1. Wrap NTL's ZZ into Python exactly as you would wrap any other C++
class. You would then use ZZ both within Python and C++, and existence
of Python's native long integer is simply ignored.

2. Provide conversion functions between Python's native long integer and
NTL's ZZ. Then you would use the former within Python, and the latter
within C++. Conversion functions would look like this:

    ZZ from_python(PyObject* p, py::Type<ZZ>)
    {
        ZZ result;
        if(PyInt_Check(p))
        {
            result = to_ZZ(PyInt_AsLong(p));
        }
        else if (PyLong_Check(p))
        {
            PyLongObject * pl = (PyLongObject *)p;
            ... // create an octet string from pl
            ZZFromBytes(result, bytes, size);
        }
        else
        {
            PyErr_SetString(PyExc_TypeErr, "int or long required");
            throw py::ArgumentError();
        }
        return result;
    }

    PyObject * to_python(ZZ const & number)
    {
        int size = NumBytes(number);
        unsigned char * bytes = new unsigned char[size];
        BytesFromZZ(bytes, number, size);
    
        int pythonSize = ...; // some function of size
        PyLongObject * pl = _PyLong_New(pythonSize);
        ... // convert bytes to pl's internal structure
        return pl;
    }

When you wrap a NTL function that takes a ZZ as an argument, the above
'from_python()' function is automatically called. Likewise 'to_python()'
is called when a function returns a ZZ. Note, however, that you *cannot*
wrap functions that return their result in a reference parameter that is
overwritten (i.e. you cannot wrap 'conv(ZZ &, int)'). Another problem
with this approach is that the methods to access the internal
representation of a PyLongObject are not part of the official Python/C
API. So you should probably stick to solution 1. A combination of both
solutions might also be possible.

Regards
Ulli

-- 
 ________________________________________________________________
|                                                                |
| Ullrich Koethe  Universität Hamburg / University of Hamburg    |
|                 FB Informatik / Dept. of Computer Science      |
|                 AB Kognitive Systeme / Cognitive Systems Group |
|                                                                |
| Phone: +49 (0)40 42883-2573                Vogt-Koelln-Str. 30 |
| Fax:   +49 (0)40 42883-2572                D - 22527 Hamburg   |
| Email: u.koethe_at_[hidden]               Germany             |
|        koethe_at_[hidden]                        |
| WWW:   http://kogs-www.informatik.uni-hamburg.de/~koethe/      |
|________________________________________________________________|

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