mirror of
https://github.com/boostorg/python.git
synced 2026-01-20 16:52:15 +00:00
232 lines
5.9 KiB
C++
232 lines
5.9 KiB
C++
// Copyright David Hawkes 2002.
|
|
// Permission is hereby granted to copy, use and modify this software
|
|
// for any purpose, including commercial distribution, provided this
|
|
// copyright notice is not removed. No warranty WHATSOEVER is provided with this
|
|
// software. Any user(s) accepts this software "as is" and as such they will not
|
|
// bind the author(s) to any claim of suitabilty for any purpose.
|
|
|
|
// embed_test.cpp : substantial test of embedding python in c++ using boost
|
|
|
|
#include <boost/python/module.hpp>
|
|
#include <boost/python/class.hpp>
|
|
#include <boost/python/call_method.hpp>
|
|
#include <boost/python/call.hpp>
|
|
#include <boost/python/object.hpp>
|
|
#include <boost/python/py_interface.hpp>
|
|
#include <boost/utility.hpp>
|
|
#include <boost/shared_ptr.hpp>
|
|
|
|
using namespace boost;
|
|
using namespace boost::python;
|
|
|
|
|
|
// The following macros are for our convenience and coding expediency...
|
|
// There is no particular recomendation that they be used elsewhere
|
|
// as they are not feature complete and are just sufficient to suport
|
|
// the code here
|
|
|
|
|
|
#define DEF(fn) def(#fn, fn)
|
|
#define DEF_C(c, fn) def(#fn, &c::fn)
|
|
#define DEF_C_CB(c, fn) def(#fn, &c##_callback::base_##fn)
|
|
|
|
#define CLASS(c) class_<c, shared_ptr<c> >(#c)
|
|
#define CLASS_CB(c) class_<c, shared_ptr<c##_callback>, noncopyable >(#c)
|
|
|
|
#define START_CALLBACK_CLASS(c) \
|
|
class c##_callback : public c \
|
|
{ \
|
|
typedef c __base__; \
|
|
public: \
|
|
c##_callback(PyObject* self) : m_self(self) {} \
|
|
private: \
|
|
PyObject* m_self; \
|
|
public:
|
|
|
|
#define END_CALLBACK_CLASS };
|
|
|
|
|
|
#define CALLBACK_MEMBER0(fn, rtn) \
|
|
rtn fn() { return call_method<rtn>(m_self, #fn); } \
|
|
rtn base_##fn() { return __base__::fn(); }
|
|
|
|
|
|
#define CALLBACK_MEMBER0C(fn, rtn) \
|
|
rtn fn() const { return call_method<rtn>(m_self, #fn); } \
|
|
rtn base_##fn() const { return __base__::fn(); }
|
|
// End of convenience macros
|
|
|
|
// useful support classes
|
|
template<class T>
|
|
struct class_object : public object
|
|
{
|
|
typedef object base;
|
|
class_object() : m_class_ptr(NULL) {}
|
|
class_object(object const& o) : base(o) { init(); }
|
|
class_object& operator=(object const& o)
|
|
{
|
|
base::operator=(o);
|
|
init();
|
|
return *this;
|
|
}
|
|
T* operator->() const { return m_class_ptr; }
|
|
T& operator*() const { return *m_class_ptr; }
|
|
private:
|
|
void init()
|
|
{
|
|
m_class_ptr = arg_from_python<T*>(ptr())(ptr());
|
|
}
|
|
T* m_class_ptr;
|
|
};
|
|
|
|
template<class T>
|
|
struct item_object : public object
|
|
{
|
|
typedef object base;
|
|
item_object() {}
|
|
item_object(object const& o) : base(o), m_class(arg_from_python<T>(ptr())(ptr())) {}
|
|
item_object& operator=(object const& o)
|
|
{
|
|
base::operator=(o);
|
|
init();
|
|
return *this;
|
|
}
|
|
operator T() { return m_class; }
|
|
private:
|
|
void init()
|
|
{
|
|
m_class = arg_from_python<T>(ptr())(ptr());
|
|
}
|
|
T m_class;
|
|
};
|
|
// end of useful support classes
|
|
|
|
// pass our args in this struct
|
|
struct main_args {
|
|
main_args(int _argc, char* _argv[]) : argc(_argc), argv(_argv) {}
|
|
int argc;
|
|
char** argv;
|
|
};
|
|
int python_main(main_args const &ma);
|
|
|
|
// python module init
|
|
BOOST_PYTHON_MODULE(python_main)
|
|
{
|
|
DEF(python_main);
|
|
CLASS(main_args);
|
|
}
|
|
|
|
// sub module tests
|
|
namespace sm {
|
|
|
|
int test_func() { return 7; }
|
|
|
|
BOOST_PYTHON_MODULE(sm_test)
|
|
{
|
|
// define a submodule
|
|
boost::python::module(".sm");
|
|
// define a 2nd submodule
|
|
boost::python::module(".sm.sm2");
|
|
// define a test function to appear in 2nd submodule
|
|
DEF(test_func);
|
|
}
|
|
|
|
// sub-module tests
|
|
int test()
|
|
{
|
|
api::run_simple_string("import sm_test");
|
|
if(api::call_statement("_0 = bpl_test('sub modules', sm_test.sm.sm2.test_func, _1)", test_func()))
|
|
return 1;
|
|
return 0;
|
|
}
|
|
|
|
}
|
|
|
|
// sub class tests
|
|
namespace sc {
|
|
|
|
class c1 {
|
|
public:
|
|
c1() {}
|
|
class c2 {
|
|
public:
|
|
c2() : n(2) {}
|
|
int n;
|
|
};
|
|
c2 t;
|
|
};
|
|
|
|
c1::c2 test_func() {
|
|
return c1().t;
|
|
}
|
|
|
|
BOOST_PYTHON_MODULE(sc_test)
|
|
{
|
|
class_<c1::c2>("c1.c2")
|
|
.def_init()
|
|
.def_readwrite("n", &c1::c2::n);
|
|
CLASS(c1)
|
|
.def_init()
|
|
.def_readwrite("t", &c1::t);
|
|
DEF(test_func);
|
|
}
|
|
|
|
// sub-class tests
|
|
int test()
|
|
{
|
|
api::run_simple_string("import sc_test");
|
|
if(api::call_statement("_0 = bpl_test('sub classes', lambda : sc_test.c1.c2().n, _1.n)", test_func()))
|
|
return 1;
|
|
if(api::call_statement("_0 = bpl_test('sub classes', lambda : sc_test.c1().t.n, _1.n)", test_func()))
|
|
return 1;
|
|
return 0;
|
|
}
|
|
|
|
}
|
|
|
|
// new main that will have a python execution frame
|
|
int main(int argc, char* argv[])
|
|
{
|
|
// default return value;
|
|
int rtn = 0;
|
|
// define all the built-in modules used
|
|
PyImport_AppendInittab("python_main", initpython_main);
|
|
PyImport_AppendInittab("sm_test", sm::initsm_test);
|
|
PyImport_AppendInittab("sc_test", sc::initsc_test);
|
|
// initialize python
|
|
Py_Initialize();
|
|
// start a new block so that any objects are released prior to finalizing
|
|
{
|
|
// import our main module - this will also initialise boost
|
|
api::run_simple_string("import python_main");
|
|
// We call back here so we have a proper python execution frame to work with
|
|
item_object<int> o_rtn(api::call_statement("_0 = python_main.python_main(_1)", main_args(argc, argv)));
|
|
rtn = o_rtn;
|
|
}
|
|
// clean up
|
|
Py_Finalize();
|
|
return rtn;
|
|
}
|
|
|
|
char *bpl_test =
|
|
"def bpl_test(name, func, result):\n"
|
|
" print 'testing %s...' % name\n"
|
|
" if func() != result:\n"
|
|
" print 'failed'\n"
|
|
" return 1\n"
|
|
" else:\n"
|
|
" print 'OK'\n"
|
|
" return 0\n";
|
|
|
|
|
|
int python_main(main_args const &ma)
|
|
{
|
|
api::print("running...\n");
|
|
api::call_statement(bpl_test);
|
|
if(sm::test())
|
|
return 1;
|
|
if(sc::test())
|
|
return 1;
|
|
return 0;
|
|
}
|