File: simple.cxx

package info (click to toggle)
pycxx 7.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 1,276 kB
  • sloc: cpp: 6,617; python: 874; sh: 102; ansic: 60; makefile: 54
file content (382 lines) | stat: -rw-r--r-- 13,082 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
//
//  Copyright (c) 2008-2010 Barry A. Scott
//
//
//  simple_moduile.cxx
//
//  This module defines a single function.
//
#ifdef _MSC_VER
// disable warning C4786: symbol greater than 255 character,
// nessesary to ignore as <map> causes lots of warning
#pragma warning(disable: 4786)
#endif

#include "CXX/Objects.hxx"
#include "CXX/Extensions.hxx"

#include <assert.h>


class new_style_class: public Py::PythonClass< new_style_class >
{
public:
    new_style_class( Py::PythonClassInstance *self, Py::Tuple &args, Py::Dict &kwds )
    : Py::PythonClass< new_style_class >::PythonClass( self, args, kwds )
    , m_value( "default value" )
    {
        std::cout << "new_style_class c'tor Called with " << args.length() << " normal arguments." << std::endl;
        Py::List names( kwds.keys() );
        std::cout << "and with " << names.length() << " keyword arguments:" << std::endl;
        for( Py::List::size_type i=0; i< names.length(); i++ )
        {
            Py::String name( names[i] );
            std::cout << "    " << name << std::endl;
        }
    }

    virtual ~new_style_class()
    {
        std::cout << "~new_style_class." << std::endl;
    }

    int cxx_method( int a, int b )
    {
        return a * b + 3;
    }

    static void init_type(void)
    {
        behaviors().name( "new_style_class" );
        behaviors().doc( "documentation for new_style_class class" );
        behaviors().supportGetattro();
        behaviors().supportSetattro();

        PYCXX_ADD_NOARGS_METHOD( func_noargs, new_style_class_func_noargs, "docs for func_noargs" );
        PYCXX_ADD_VARARGS_METHOD( func_varargs, new_style_class_func_varargs, "docs for func_varargs" );
        PYCXX_ADD_KEYWORDS_METHOD( func_keyword, new_style_class_func_keyword, "docs for func_keyword" );

        PYCXX_ADD_NOARGS_METHOD( func_noargs_raise_exception, new_style_class_func_noargs_raise_exception, "docs for func_noargs_raise_exception" );

        PYCXX_ADD_VARARGS_METHOD( func_varargs_call_member, new_style_class_call_member, "docs for func_varargs_call_member" );

        // Call to make the type ready for use
        behaviors().readyType();
    }

    Py::Object new_style_class_func_noargs( void )
    {
        std::cout << "new_style_class_func_noargs Called." << std::endl;
        std::cout << "value ref count " << m_value.reference_count() << std::endl;
        return Py::None();
    }
    PYCXX_NOARGS_METHOD_DECL( new_style_class, new_style_class_func_noargs )

    Py::Object new_style_class_func_varargs( const Py::Tuple &args )
    {
        std::cout << "new_style_class_func_varargs Called with " << args.length() << " normal arguments." << std::endl;
        return Py::None();
    }
    PYCXX_VARARGS_METHOD_DECL( new_style_class, new_style_class_func_varargs )

    Py::Object new_style_class_call_member( const Py::Tuple &args )
    {
        std::cout << "new_style_class_call_member Called with " << args.length() << " normal arguments." << std::endl;

        Py::String member_func_name( args[0] );

#ifdef PYCXX_DEBUG
        bpt();
#endif
        Py::Object _self = self();
        try
        {
            Py::Object result( _self.callMemberFunction( member_func_name.as_std_string(), args ) );
            return result;
        }
        catch( Py::BaseException &e )
        {
            e.clear();
            return Py::String( "new_style_class_call_member error when calling member" );
        }
    }
    PYCXX_VARARGS_METHOD_DECL( new_style_class, new_style_class_call_member )

    Py::Object new_style_class_func_keyword( const Py::Tuple &args, const Py::Dict &kwds )
    {
        std::cout << "new_style_class_func_keyword Called with " << args.length() << " normal arguments." << std::endl;
        Py::List names( kwds.keys() );
        std::cout << "and with " << names.length() << " keyword arguments:" << std::endl;
        for( Py::List::size_type i=0; i< names.length(); i++ )
        {
            Py::String name( names[i] );
            std::cout << "    " << name << std::endl;
        }
        return Py::None();
    }
    PYCXX_KEYWORDS_METHOD_DECL( new_style_class, new_style_class_func_keyword )

    Py::Object new_style_class_func_noargs_raise_exception( void )
    {
        std::cout << "new_style_class_func_noargs_raise_exception Called." << std::endl;
        throw Py::RuntimeError( "its an error" );
    }
    PYCXX_NOARGS_METHOD_DECL( new_style_class, new_style_class_func_noargs_raise_exception )

    Py::Object getattro( const Py::String &name_ )
    {
        std::string name( name_.as_std_string( "utf-8" ) );

        if( name == "value" )
        {
            return m_value;
        }
        else
        {
            return genericGetAttro( name_ );
        }
    }

    int setattro( const Py::String &name_, const Py::Object &value )
    {
        std::string name( name_.as_std_string( "utf-8" ) );

        if( name == "value" )
        {
            m_value = value;
            return 0;
        }
        else
        {
            return genericSetAttro( name_, value );
        }
    }


    Py::String m_value;
};

class old_style_class: public Py::PythonExtension< old_style_class >
{
public:
    old_style_class()
    {
    }

    virtual ~old_style_class()
    {
    }

    static void init_type(void)
    {
        behaviors().name( "old_style_class" );
        behaviors().doc( "documentation for old_style_class class" );
        behaviors().supportGetattr();

        add_noargs_method( "old_style_class_func_noargs", &old_style_class::old_style_class_func_noargs );
        add_varargs_method( "old_style_class_func_varargs", &old_style_class::old_style_class_func_varargs );
        add_keyword_method( "old_style_class_func_keyword", &old_style_class::old_style_class_func_keyword );
    }

    // override functions from PythonExtension
    virtual Py::Object getattr( const char *name )
    {
        return getattr_methods( name );
    }

    Py::Object old_style_class_func_noargs( void )
    {
        std::cout << "old_style_class_func_noargs Called." << std::endl;
        return Py::None();
    }

    Py::Object old_style_class_func_varargs( const Py::Tuple &args )
    {
        std::cout << "old_style_class_func_varargs Called with " << args.length() << " normal arguments." << std::endl;
        return Py::None();
    }

    Py::Object old_style_class_func_keyword( const Py::Tuple &args, const Py::Dict &kwds )
    {
        std::cout << "old_style_class_func_keyword Called with " << args.length() << " normal arguments." << std::endl;
        Py::List names( kwds.keys() );
        std::cout << "and with " << names.length() << " keyword arguments:" << std::endl;
        for( Py::List::size_type i=0; i< names.length(); i++ )
        {
            Py::String name( names[i] );
            std::cout << "    " << name << std::endl;
        }
        return Py::None();
    }
};

PYCXX_USER_EXCEPTION_STR_ARG( SimpleError )

class simple_module : public Py::ExtensionModule<simple_module>
{
public:
    simple_module()
    : Py::ExtensionModule<simple_module>( "simple" ) // this must be name of the file on disk e.g. simple.so or simple.pyd
    {
        old_style_class::init_type();
        new_style_class::init_type();

        add_varargs_method("old_style_class", &simple_module::factory_old_style_class, "documentation for old_style_class()");
        add_keyword_method("func", &simple_module::func, "documentation for func()");
        add_keyword_method("func_with_callback", &simple_module::func_with_callback, "documentation for func_with_callback()");
        add_keyword_method("func_with_callback_catch_simple_error", &simple_module::func_with_callback_catch_simple_error, "documentation for func_with_callback_catch_simple_error()");
        add_keyword_method("make_instance", &simple_module::make_instance, "documentation for make_instance()");

        add_keyword_method("decode_test", &simple_module::decode_test, "documentation for decode_test()");
        add_keyword_method("encode_test", &simple_module::encode_test, "documentation for encode_test()");
        add_keyword_method("derived_class_test", &simple_module::derived_class_test, "documentation for derived_class_test()");
 
        // after initialize the moduleDictionary will exist
        initialize( "documentation for the simple module" );

        Py::Dict d( moduleDictionary() );
        d["var"] = Py::String( "var value" );
        Py::Object x( new_style_class::type() );
        d["new_style_class"] = x;

        SimpleError::init( *this );
    }

    virtual ~simple_module()
    {}

private:
    Py::Object decode_test( const Py::Tuple &args, const Py::Dict &/*kwds*/ )
    {
        Py::Bytes s( args[0] );
        return s.decode("utf-8");
    }

    Py::Object encode_test( const Py::Tuple &args, const Py::Dict &/*kwds*/ )
    {
        Py::String s( args[0] );
        return s.encode("utf-8");
    }

    Py::Object derived_class_test( const Py::Tuple &args, const Py::Dict &/*kwds*/ )
    {
        Py::PythonClassObject<new_style_class> py_nsc( args[0] );
        new_style_class *cxx_nsc = py_nsc.getCxxObject();

        Py::Long a( args[1] );
        Py::Long b( args[2] );

        int result = cxx_nsc->cxx_method( a, b );

        return Py::Long( result );
    }

    Py::Object func( const Py::Tuple &args, const Py::Dict &kwds )
    {
        std::cout << "func Called with " << args.length() << " normal arguments." << std::endl;
        Py::List names( kwds.keys() );
        std::cout << "and with " << names.length() << " keyword arguments:" << std::endl;
        for( Py::List::size_type i=0; i< names.length(); i++ )
        {
            Py::String name( names[i] );
            std::cout << "    " << name << std::endl;
        }

#ifdef PYCXX_DEBUG
        if( args.length() > 0 )
        {
            Py::Object x( args[0] );
            PyObject *x_p = x.ptr();
            std::cout << "func( self=0x" << std::hex << reinterpret_cast< unsigned long >( x_p ) << std::dec << " )" << std::endl;
            Py::PythonClassInstance *instance_wrapper = reinterpret_cast< Py::PythonClassInstance * >( x_p );
            new_style_class *instance = static_cast<new_style_class *>( instance_wrapper->m_pycxx_object );
            std::cout << "    self->cxx_object=0x" << std::hex << reinterpret_cast< unsigned long >( instance ) << std::dec << std::endl;
        }

        bpt();
#endif

        return Py::None();
    }

    Py::Object func_with_callback( const Py::Tuple &args, const Py::Dict &/*kwds*/ )
    {
        Py::Callable callback_func( args[0] );
        Py::Tuple callback_args( 1 );
        callback_args[0] = Py::String( "callback_args string" );

        return callback_func.apply( callback_args );
    }

    Py::Object func_with_callback_catch_simple_error( const Py::Tuple &args, const Py::Dict &/*kwds*/ )
    {
        Py::Callable callback_func( args[0] );
        Py::Tuple callback_args( 1 );
        callback_args[0] = Py::String( "callback_args string" );

        try
        {
            std::cout << "func_with_callback_catch_simple_error calling arg[0]" << std::endl;
            return callback_func.apply( callback_args );
        }
        catch( SimpleError &e )
        {
            Py::String value = Py::value( e );
            e.clear();
            std::cout << "PASS caught SimpleError( \"" << value << "\"" << std::endl;

            return Py::String("Error");
        }
    }

    Py::Object make_instance( const Py::Tuple &args, const Py::Dict &kwds )
    {
        std::cout << "make_instance Called with " << args.length() << " normal arguments." << std::endl;
        Py::List names( kwds.keys() );
        std::cout << "and with " << names.length() << " keyword arguments:" << std::endl;
        for( Py::List::size_type i=0; i< names.length(); i++ )
        {
            Py::String name( names[i] );
            std::cout << "    " << name << std::endl;
        }

        Py::Callable class_type( new_style_class::type() );

        Py::PythonClassObject<new_style_class> new_style_obj( class_type.apply( args, kwds ) );

        return new_style_obj;
    }

    Py::Object factory_old_style_class( const Py::Tuple &/*args*/ )
    {
        Py::Object obj = Py::asObject( new old_style_class );
        return obj;
    }
};

#if defined( _WIN32 )
#define EXPORT_SYMBOL __declspec( dllexport )
#else
#define EXPORT_SYMBOL
#endif

extern "C" EXPORT_SYMBOL PyObject *PyInit_simple()
{
#if defined(PY_WIN32_DELAYLOAD_PYTHON_DLL)
    Py::InitialisePythonIndirectPy::Interface();
#endif

    std::cout << "sizeof(int) " << sizeof(int) << std::endl;
    std::cout << "sizeof(long) " << sizeof(long) << std::endl;
    std::cout << "sizeof(Py_hash_t) " << sizeof(Py_hash_t) << std::endl;
    std::cout << "sizeof(Py_ssize_t) " << sizeof(Py_ssize_t) << std::endl;

    static simple_module* simple = new simple_module;
    return simple->module().ptr();
}

// symbol required for the debug version
extern "C" EXPORT_SYMBOL PyObject *PyInit_simple_d()
{ 
    return PyInit_simple();
}