Pink 0.9

ui_wrap_function.hpp File Reference

This is a helper function for exporting Pink C functions in Python. This file defines 'UI_WRAP_FUNCTION'. More...


Detailed Description

This is a helper function for exporting Pink C functions in Python. This file defines 'UI_WRAP_FUNCTION'.

This is a helper function for exporting Pink C functions in Python. This file defines 'UI_WRAP_MALLOC'.

Note

For debugging macro definitions uncomment the debug part at the end of and the beginning of the file. Then you can use the

  g++ -E -P file.cpp -o file_pp.cpp
  

commands, which outputs the source code after preprocessing. Also

  astyle -A3 -z2 -k1 -s2 -j file_pp.cpp 
  

Indents the preprocessed code and inserts lots of newlines, which improoves very much the readability of the code.

Exporting functions from C

For exporting functions from Pink you should make them follow the Conventions for developing Pink operators.

You may use printf and you may call exit(1) if there's an error. type_k can be any type that python recognizes (int, float, ...) and xvimage* The return value is 1 on success and 0 otherwise. To export this function you should include a function call in pypink.cpp of the form

  UI_WRAP_FUNCION(
  "function's name in Python",
  pink_c_function, 
  (arg("argument 1 name"), arg("argument 2 name"), ..., arg(argument n name)),
  doc__my_c_function__c__
  )
  #include BOOST_PP_UPDATE_COUNTER()

Example:

  UI_WRAP_FUNCTION(
  "ptisolated",
  lptisolated,
  ( arg("image"), arg("connexity") ),
  doc__ptisolated__c__
  );
  #include BOOST_PP_UPDATE_COUNTER()

Advanced

This file contains C++ macro language and template metaprogramming, which is difficult to understand. The file is first treated with the preprocessor. The generated code looks like this:

  // the wrapper uses boost enable_if class for conditional compilation
  // this is the base class declaration
  template <class T, class enabled = void>
  struct instance0 { };
  
  // for every number of arguments there is a special wrapper 
  // the above instantiation only occurs if the number of arguments
  // (including the 'image' object) is 1
  template <class FA>
  struct instance0< FA, typename enable_if< is_same<FA, int_<1> > >::type >
  {
    template <class Fn, class Args>
    void define(const char* fname, Fn fn, Args args, const char* doc)
    {
      // decomposition of the function for parameters
      typedef struct decompose<Fn> FT;

      // for each image type in Pink the appropriate 'make_function'
      // macro is called
      def(fname, make_function< char_image, (pink::python::ui_cheat<typename FT::result_type, xvimage*, greet>)>, args, doc);
      def(fname, make_function< short_image, (pink::python::ui_cheat<typename FT::result_type, xvimage*, greet>)>, args, doc);
      def(fname, make_function< int_image, (pink::python::ui_cheat<typename FT::result_type, xvimage*, greet>)>, args, doc);
      def(fname, make_function< float_image, (pink::python::ui_cheat<typename FT::result_type, xvimage*, greet>)>, args, doc);
      def(fname, make_function< double_image, (pink::python::ui_cheat<typename FT::result_type, xvimage*, greet>)>, args, doc);
      def(fname, make_function< fcomplex_image, (pink::python::ui_cheat<typename FT::result_type, xvimage*, greet>)>, args, doc);
      def(fname, make_function< dcomplex_image, (pink::python::ui_cheat<typename FT::result_type, xvimage*, greet>)>, args, doc);
    }
  };
  
  template <class FA> struct instance0< FA, typename enable_if< is_same<FA, int_<2> > >::type >
  {
    template <class Fn, class Args>
    void define(const char* fname, Fn fn, Args args, const char* doc)
    {
      typedef struct decompose<Fn> FT;
      def(fname, make_function< char_image, typename xv2pink< typename FT::T1 >::type, greet>, args, doc);
      def(fname, make_function< short_image, typename xv2pink< typename FT::T1 >::type, greet>, args, doc);
      def(fname, make_function< int_image, typename xv2pink< typename FT::T1 >::type, greet>, args, doc);
      def(fname, make_function< float_image, typename xv2pink< typename FT::T1 >::type, greet>, args, doc);
      def(fname, make_function< double_image, typename xv2pink< typename FT::T1 >::type, greet>, args, doc);
      def(fname, make_function< fcomplex_image, typename xv2pink< typename FT::T1 >::type, greet>, args, doc);
      def(fname, make_function< dcomplex_image, typename xv2pink< typename FT::T1 >::type, greet>, args, doc);
    }
  };
  
  template <class FA> struct instance0< FA, typename enable_if< is_same<FA, int_<3> > >::type >
  {
    template <class Fn, class Args>
    void define(const char* fname, Fn fn, Args args, const char* doc)
    {
      typedef struct decompose<Fn> FT;
      def(fname, make_function< char_image, typename xv2pink< typename FT::T1 >::type, typename xv2pink< typename FT::T2 >::type, greet>, args, doc);
      def(fname, make_function< short_image, typename xv2pink< typename FT::T1 >::type, typename xv2pink< typename FT::T2 >::type, greet>, args, doc);
      def(fname, make_function< int_image, typename xv2pink< typename FT::T1 >::type, typename xv2pink< typename FT::T2 >::type, greet>, args, doc);
      def(fname, make_function< float_image, typename xv2pink< typename FT::T1 >::type, typename xv2pink< typename FT::T2 >::type, greet>, args, doc);
      def(fname, make_function< double_image, typename xv2pink< typename FT::T1 >::type, typename xv2pink< typename FT::T2 >::type, greet>, args, doc);
      def(fname, make_function< fcomplex_image, typename xv2pink< typename FT::T1 >::type, typename xv2pink< typename FT::T2 >::type, greet>, args, doc);
      def(fname, make_function< dcomplex_image, typename xv2pink< typename FT::T1 >::type, typename xv2pink< typename FT::T2 >::type, greet>, args, doc);
    }
  };
  
  // this function does the first decomposition and the 
  // appropriate wrapper class instantiation
  template <class Fn, class Args>
  void call0(const char* fname, Fn fn, Args args, const char* doc)
  {
    const int FA = decompose<Fn>::arity;
    instance0< int_<FA> > wrapped_function;
    wrapped_function.define(fname, fn, args, doc);
  }
  
  // this is a helper function so we wouldn't have to 
  // call call0 again in 'BOOST_PYTHON_MODULE'
  void export_function0()
  {
    call0("greet", greet, (arg("image"), (arg("int"))), "WRITE ME!!");
  };

The macro generates the wrapper 'instance' for each number of parameters. The template takes the specified parameters and wraps the function in Python. The most important part of the macro is the conversion of the 'xvimage*' pointer into the appropriate image class (like 'char_image').

Note

For debugging macro definitions uncomment the debug part at the end of and the beginning of the file. Then you can use the

  g++ -E -P file.cpp -o file_pp.cpp
  

commands, which outputs the source code after preprocessing. Also

  astyle -A3 -z2 -k1 -s2 -j file_pp.cpp 
  

Indents the preprocessed code and inserts lots of newlines, which improoves very much the readability of the code.

Exporting functions from C

For exporting functions from Pink you should make them follow the Conventions for developing Pink operators.

You may use printf and you may call exit(1) if there's an error. type_k can be any type that python recognizes (int, float, ...) and xvimage* The return value is 1 on success and 0 otherwise. To export this function you should include a function call in pypink.cpp of the form

  UI_WRAP_FUNCION(
  "function's name in Python",
  pink_c_function, 
  (arg("argument 1 name"), arg("argument 2 name"), ..., arg(argument n name)),
  doc__my_c_function__c__
  )
  #include BOOST_PP_UPDATE_COUNTER()

Example:

  UI_WRAP_MALLOC(
  "ptisolated",
  lptisolated,
  ( arg("image"), arg("connexity") ),
  doc__ptisolated__c__
  );
  #include BOOST_PP_UPDATE_COUNTER()

Advanced

This file contains C++ macro language and template metaprogramming, which is difficult to understand. The file is first treated with the preprocessor. The generated code looks like this:

  // the wrapper uses boost enable_if class for conditional compilation
  // this is the base class declaration
  template <class T, class enabled = void>
  struct instance0 { };
  
  // for every number of arguments there is a special wrapper 
  // the above instantiation only occurs if the number of arguments
  // (including the 'image' object) is 1
  template <class FA>
  struct instance0< FA, typename enable_if< is_same<FA, int_<1> > >::type >
  {
    template <class Fn, class Args>
    void define(const char* fname, Fn fn, Args args, const char* doc)
    {
      // decomposition of the function for parameters
      typedef struct decompose<Fn> FT;

      // for each image type in Pink the appropriate 'make_malloc'
      // macro is called
      def(fname, make_malloc< char_image, (pink::python::ui_cheat<typename FT::result_type, xvimage*, greet>)>, args, doc);
      def(fname, make_malloc< short_image, (pink::python::ui_cheat<typename FT::result_type, xvimage*, greet>)>, args, doc);
      def(fname, make_malloc< int_image, (pink::python::ui_cheat<typename FT::result_type, xvimage*, greet>)>, args, doc);
      def(fname, make_malloc< float_image, (pink::python::ui_cheat<typename FT::result_type, xvimage*, greet>)>, args, doc);
      def(fname, make_malloc< double_image, (pink::python::ui_cheat<typename FT::result_type, xvimage*, greet>)>, args, doc);
      def(fname, make_malloc< fcomplex_image, (pink::python::ui_cheat<typename FT::result_type, xvimage*, greet>)>, args, doc);
      def(fname, make_malloc< dcomplex_image, (pink::python::ui_cheat<typename FT::result_type, xvimage*, greet>)>, args, doc);
    }
  };
  
  template <class FA> struct instance0< FA, typename enable_if< is_same<FA, int_<2> > >::type >
  {
    template <class Fn, class Args>
    void define(const char* fname, Fn fn, Args args, const char* doc)
    {
      typedef struct decompose<Fn> FT;
      def(fname, make_malloc< char_image, typename xv2pink< typename FT::T1 >::type, greet>, args, doc);
      def(fname, make_malloc< short_image, typename xv2pink< typename FT::T1 >::type, greet>, args, doc);
      def(fname, make_malloc< int_image, typename xv2pink< typename FT::T1 >::type, greet>, args, doc);
      def(fname, make_malloc< float_image, typename xv2pink< typename FT::T1 >::type, greet>, args, doc);
      def(fname, make_malloc< double_image, typename xv2pink< typename FT::T1 >::type, greet>, args, doc);
      def(fname, make_malloc< fcomplex_image, typename xv2pink< typename FT::T1 >::type, greet>, args, doc);
      def(fname, make_malloc< dcomplex_image, typename xv2pink< typename FT::T1 >::type, greet>, args, doc);
    }
  };
  
  template <class FA> struct instance0< FA, typename enable_if< is_same<FA, int_<3> > >::type >
  {
    template <class Fn, class Args>
    void define(const char* fname, Fn fn, Args args, const char* doc)
    {
      typedef struct decompose<Fn> FT;
      def(fname, make_malloc< char_image, typename xv2pink< typename FT::T1 >::type, typename xv2pink< typename FT::T2 >::type, greet>, args, doc);
      def(fname, make_malloc< short_image, typename xv2pink< typename FT::T1 >::type, typename xv2pink< typename FT::T2 >::type, greet>, args, doc);
      def(fname, make_malloc< int_image, typename xv2pink< typename FT::T1 >::type, typename xv2pink< typename FT::T2 >::type, greet>, args, doc);
      def(fname, make_malloc< float_image, typename xv2pink< typename FT::T1 >::type, typename xv2pink< typename FT::T2 >::type, greet>, args, doc);
      def(fname, make_malloc< double_image, typename xv2pink< typename FT::T1 >::type, typename xv2pink< typename FT::T2 >::type, greet>, args, doc);
      def(fname, make_malloc< fcomplex_image, typename xv2pink< typename FT::T1 >::type, typename xv2pink< typename FT::T2 >::type, greet>, args, doc);
      def(fname, make_malloc< dcomplex_image, typename xv2pink< typename FT::T1 >::type, typename xv2pink< typename FT::T2 >::type, greet>, args, doc);
    }
  };
  
  // this function does the first decomposition and the 
  // appropriate wrapper class instantiation
  template <class Fn, class Args>
  void call0(const char* fname, Fn fn, Args args, const char* doc)
  {
    const int FA = decompose<Fn>::arity;
    instance0< int_<FA> > wrapped_function;
    wrapped_function.define(fname, fn, args, doc);
  }
  
  // this is a helper function so we wouldn't have to 
  // call call0 again in 'BOOST_PYTHON_MODULE'
  void export_function0()
  {
    call0("greet", greet, (arg("image"), (arg("int"))), "WRITE ME!!");
  };

The macro generates the wrapper 'instance' for each number of parameters. The template takes the specified parameters and wraps the function in Python. The most important part of the macro is the conversion of the 'xvimage*' pointer into the appropriate image class (like 'char_image').