简体   繁体   English

如何在Boost Python中公开带有可变参数的C ++函数

[英]How to expose a c++ function taking variable arguments in boost python

I have a c++ function taking variable number of arguments. 我有一个c ++函数接受可变数量的参数。

   char const* Fun(int num, ...)
   {
   ....//does some processing on the arguments passed
   }

Boost Python code for exposing this function is written as, 用于公开此功能的Boost Python代码编写为:

    using namespace boost::python;
    BOOST_PYTHON_MODULE( lib_boost )
   {
       def( "Fun", Fun );
   }

while compiling this code gives the below error 在编译此代码时出现以下错误

In file included from /boost_1_42_0/boost/python/data_members.hpp:15, from /boost_1_42_0/boost/python/class.hpp:17, from /boost_1_42_0/boost/python.hpp:18, from Lib_boost.h:3, from Lib_boost.cpp:1: /boost_1_42_0/boost/python/make_function.hpp: In function 'boost::python::api::object boost::python::make_function(F) [with F = const char* ( )(int, ...)]': /boost_1_42_0/boost/python/def.hpp:82: 在/boost_1_42_0/boost/python/data_members.hpp:15、/boost_1_42_0/boost/python/class.hpp:17、/boost_1_42_0/boost/python.hpp:18、Lib_boost.h:3,来自Lib_boost.cpp:1:/boost_1_42_0/boost/python/make_function.hpp:在功能'boost :: python :: api :: object boost :: python :: make_function(F)[with F = const char *( ) (int,...)]':/ boost_1_42_0 / boost / python / def.hpp:82:
instantiated from 'boost::python::api::object boost::python::detail::make_function1(T, ...) [with T = const char ( )(int, ...)]' /boost_1_42_0/boost/python/def.hpp:91: instantiated from 'void boost::python::def(const char , Fn) [with Fn = const char* ( )(int, ...)]' Lib_boost.cpp:540: instantiated from here /boost_1_42_0/boost/python/make_function.hpp:104: error: invalid conversion from 'const char ( )(int, ...)' to 'const char ( )(int) /boost_1_42_0/boost/python/make_function.hpp:104: error: 从'boost :: python :: api :: object boost :: python :: detail :: make_function1(T,...)[with T = const char)(int,...)]实例化'/ boost_1_42_0 / boost / python / def.hpp:91:从'void boost :: python :: def(const char ,Fn)[与Fn = const char *( )(int,...)]实例化“ Lib_boost.cpp:540 :从此处实例化/boost_1_42_0/boost/python/make_function.hpp:104:错误:从'const char)(int,...)'到'const char)(int)/ boost_1_42_0 / boost / python的 无效转换 /make_function.hpp:104:错误:
initializing argument 1 of 'boost::mpl::vector2 boost::python::detail::get_signature(RT ( )(T0), void*) [with RT = const char*, T0 = int]' 初始化'boost :: mpl :: vector2 boost :: python :: detail :: get_signature(RT( )(T0),void *)[with RT = const char *,T0 = int]的参数1

My understanding from the error info above is boost python could not recognize the function taking variable arguments(invalid conversion from 'const char* ( )(int, ...)' to 'const char (*)(int)') 从上面的错误信息中我的理解是boost python无法识别带有可变参数的函数(从'const char *( )(int,...)'到'const char (*)(int)'的无效转换)

Exposing a function with fixed/known set of arguments is not the same for functions taking variable arguments. 公开带有固定/已知参数集的函数与采用可变参数的函数不同。 How to expose a function with variable arguments? 如何公开带有可变参数的函数?

I find the best way to treat variadic arguments is by using raw_function . 我发现处理可变参数的最佳方法是使用raw_function This way you get full control in converting your C++ parameters into Python objects: 通过这种方式,您可以完全控制将C ++参数转换为Python对象:

The wrapper: 包装器:

using namespace boost::python;

object fun(tuple args, dict kwargs)
{
    char* returned_value;

    for(int i = 0; i < len(args); ++i) {
        // Extract the args[i] into a C++ variable,
        // build up your argument list
    }

    // build your parameter list from args and kwargs 
    // and pass it to your variadic c++ function

    return str(returned_value);
}

The declaration: 声明:

def("fun", raw_function(fun, 1) );

raw_function takes two arguments: the function pointer and minimum number of arguments. raw_function有两个参数:函数指针和最小数量的参数。

if you are using c++11 then following could work ( tested on g++-4.8.2 ) 如果您使用的是c ++ 11,则可以执行以下操作(在g ++-4.8.2上测试)

#include <boost/python.hpp>
#include <boost/python/list.hpp>
#include <vector>
#include <string>
#include <cstdarg>
#include <cassert>

using namespace boost::python;

template <int... Indices>
struct indices
{
    using next = indices<Indices..., sizeof...(Indices)>;
};

template <int N>
struct build_indices
{
    using type = typename build_indices<N-1>::type::next;
};

template <>
struct build_indices<0>
{
    using type = indices<>;
};
template <int N>
using BuildIndices = typename build_indices<N>::type;

template <int num_args>
class unpack_caller
{
private:
    template <typename FuncType, int... I>
    char * call(FuncType &f, std::vector<char*> &args, indices<I...>)
    {
        return f(args.size(), args[I]...);
    }

public:
    template <typename FuncType>
    char * operator () (FuncType &f, std::vector<char*> &args)
    {
        assert( args.size() <= num_args );
        return call(f, args, BuildIndices<num_args>{});
    }
};

//This is your function that you wish to call from python
char * my_func( int a, ... )
{
    //do something ( this is just a sample )
    static std::string ret;

    va_list ap;
    va_start (ap, a);
    for( int i = 0; i < a; ++i)
    {
        ret += std::string( va_arg (ap, char * ) );
    }

    va_end (ap);
    return (char *)ret.c_str();
}

std::string my_func_overload( list & l )
{
    extract<int> str_count( l[0] );
    if( str_count.check() )
    {
        int count = str_count();
        std::vector< char * > vec;
        for( int index = 1; index <= count; ++index )
        {
            extract< char * > str( l[index] );
            if( str.check() )
            {
                //extract items from list and build vector
                vec.push_back( str() );
            }
        }
        //maximum 20 arguments will be processed.
        unpack_caller<20> caller;

        return std::string( caller( my_func, vec ) );
    }

    return std::string("");
}

BOOST_PYTHON_MODULE(my_module)
{
    def("my_func", my_func_overload )
    ;
}

In python: 在python中:

Python 2.7.6 (default, Mar 22 2014, 22:59:38) 
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import my_module as m
>>> m.my_func([5, "my", " first", " five", " string", " arguments"])
'my first five string arguments'
>>>

In this example "char * my_func( int a, ... )" simply concatenates all the string arguments and returns the resulting string. 在此示例中,“ char * my_func(int a,...)”仅连接所有字符串参数并返回结果字符串。

You can probably do it by treating the arguments as optional, so long as you know what the maximum count can be. 只要知道最大数量是多少,就可以通过将参数视为可选参数来实现。 See here: https://wiki.python.org/moin/boost.python/FunctionOverloading 看到这里: https : //wiki.python.org/moin/boost.python/FunctionOverloading

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 C++ 和 Boost.Python - 如何将变量暴露给 python 并在循环中更新它? - C++ and Boost.Python - how to expose variable to python and update it in loop? 如何使用 boost/python 将 C++ 虚函数公开给 python? - How to expose C++ virtual functions to python using boost/python? 如何在不使用Boost的情况下将C ++类公开给Python? - How to expose C++ class to Python without using Boost? boost-python - 使用默认参数公开C ++(非纯)虚方法 - boost-python - expose C++ (non-pure) virtual method with default arguments Boost Python使用std :: vectors作为参数导入C ++函数 - Boost Python importing a C++ function with std::vectors as arguments 使用boost :: python公开具有std :: function作为参数的C ++成员函数 - Expose C++ member function that has std::function as argument with boost::python 在Python中公开C ++全局变量 - Expose a C++ global variable in Python 如何使用Cython公开将C ++对象返回给Python的函数? - How to expose a function returning a C++ object to Python using Cython? boost :: python:将C ++类暴露给C ++应用程序中嵌入的python脚本 - boost::python: expose a C++ class to a python script embedded in a C++ app 从boost python调用具有可变数量的输入参数的Python函数 - calling a Python function with variable number of input arguments from boost python
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM