Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/matlab/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何将类成员方法的参数列表自动填充到可变参数中? 我最近在C++中写了一个Python 3的扩展,但是在Python中调用C++时遇到了一些麻烦。_Python_C++_Python 3.x_Visual C++_Python C Api - Fatal编程技术网

如何将类成员方法的参数列表自动填充到可变参数中? 我最近在C++中写了一个Python 3的扩展,但是在Python中调用C++时遇到了一些麻烦。

如何将类成员方法的参数列表自动填充到可变参数中? 我最近在C++中写了一个Python 3的扩展,但是在Python中调用C++时遇到了一些麻烦。,python,c++,python-3.x,visual-c++,python-c-api,Python,C++,Python 3.x,Visual C++,Python C Api,我不知道如何封装下面的代码,而不需要编写每次重复的回调函数 我正在考虑以某种形式绑定回调函数和参数列表,但我不知道如何做到这一点 这是我的主要代码: class TestClass { PyObject_HEAD public: int add(int a, int b) { return (a + b); } }; // ... Ignore some details here ... static PyObject* function1(Tes

我不知道如何封装下面的代码,而不需要编写每次重复的回调函数

我正在考虑以某种形式绑定回调函数和参数列表,但我不知道如何做到这一点

这是我的主要代码:

class TestClass
{
    PyObject_HEAD
public:

    int add(int a, int b) {
        return (a + b);
    }

};

// ... Ignore some details here ...

static PyObject* function1(TestClass *self, PyObject* args) {

    // How to changed the following code to take the value from PyArg_ParseTuple
    // through the binding function and parameter list?
    int a, b;
    if (!PyArg_ParseTuple(args, "ii", &a, &b))
    {
        return nullptr;
    }

    // How to changed the following code to the return type of the binding function?
    return Py_BuildValue("i", self->add(a, b));
}

是否可以实现像BINDING_FUNCTIONTestClass::add这样的调用;在某种程度上?

是的,这是可能的,但它需要大量的代码。我认为太多了,很难在这里找到答案

好消息是,其他人已经编写了您需要的代码并将它们放入库中。我知道的那些是现代的,而且有点老

您可以查看这些库是如何做到这一点的,也可以实际使用这些库

如果您确实想自己完成此操作,则需要大致步骤:

创建泛型函数以从函数参数类型和返回类型创建格式字符串 创建模板元函数以定义元组类型以保存给定成员函数的参数 实现可以使用PyArg_ParseTuple填充此类元组的通用函数。这将使用格式字符串生成函数和元组定义 实现一个通用函数,该函数接受一个对象、一个成员函数指针和一个带参数的元组,并使用给定参数调用成员函数。那么如何做到这一点。 通常,您希望将最后一个函数专门化为void返回类型函数,如果您希望在成员函数之外支持自由函数,则可能需要编写一些额外的代码

下面的代码仅用于教育目的,因为它是上述步骤的一个非常简化的实现。前面提到的库实现了许多本代码没有解决的关键情况

#include <iostream>
#include <sstream>
#include <type_traits>
#include <tuple>

// some object we want to wrap
struct Duck
{
    int MemberFunc( int x, int y, float w)
    {
        std::cout << "Member function called\n";
        return x+ w * y;
    }
};


// PART 1: create format strings for function argument- and return types

// "excercise for the reader": implement these overloads for all supported types
template<typename T> struct Tag{};
const char *GetTypeFormat( const Tag<int>&)
{
    return "i";
}
const char *GetTypeFormat( const Tag<float>&)
{
    return "f";
}

// create a format string from a list of argument types
template< typename... Args>
void GetTypeFormats( std::ostream &strm)
{
    (void)(int[]){0, ((strm << GetTypeFormat(Tag<Args>{})),0)...};
}

// this is quite inefficient because it creates the format string at 
// run-time. Doing this as constexpr is an interesting challenge
// ("...for the reader")
template< typename R, typename Class, typename... Args>
std::string GetArgumentFormats( R (Class::*f)(Args...))
{
     std::stringstream strm;
     GetTypeFormats<Args...>( strm);
     return strm.str();
}

template< typename R, typename Class, typename... Args>
std::string GetReturnFormat( R (Class::*f)(Args...))
{
     std::stringstream strm;
     GetTypeFormats<R>( strm);
     return strm.str();
}

// PART 2: declare std::tuple-type to hold function arguments

// given a list of types that could be function parameter types, define a 
// tuple type that can hold all argument values to such a function
// THIS IS VERY MUCH A SIMPLIFIED IMPLEMENTATION
// This doesn't take pointer types into account for instance.
template< typename F>
struct ArgumentTuple {};

template< typename R, typename Class, typename... Args>
struct ArgumentTuple<R (Class::*)( Args...)>
{
    using type = std::tuple<
        typename std::remove_cv<
            typename std::remove_reference<Args>::type>::type...>;
};


// for demo purposes. emulate python binding functions
using PyObject = void;
bool PyArg_ParseTuple( PyObject *, const char *, ...) {}
template< typename T>
PyObject *Py_BuildValue( const char*, T ){}

// PART 3: given some function pointer, obtain arguments from a PyObject
template<typename F, size_t... Indexes>
auto FillTuple( PyObject *obj, F f, std::index_sequence<Indexes...>) -> typename ArgumentTuple<F>::type
{
    using std::get;
    typename ArgumentTuple<F>::type arguments;
    // no error checking whatsoever: "exercise for the reader" 

    PyArg_ParseTuple( obj, GetArgumentFormats( f).c_str(), &get<Indexes>( arguments)...);
    return arguments;
}

template< typename R, typename Class, typename... Args>
auto FillTuple( PyObject *obj, R (Class::*f)(Args...))
{
    return FillTuple( obj, f, std::index_sequence_for<Args...>{});
}

// PART 4, call a member function given a tuple of arguments

// helper function
template< 
    typename R, 
    typename Class, 
    typename MF, 
    typename ArgumentTuple, 
    size_t... Indexes>
R Apply( Class &obj, MF f, ArgumentTuple &args, std::index_sequence<Indexes...>)
{
    using std::get;
    return (obj.*f)( get<Indexes>( args)...);
}

// Apply a (member-) function to a tuple of arguments.
template<
    typename R,
    typename Class,
    typename ArgumentTuple,
    typename... Args>
R Apply( Class &obj, R (Class::*f)( Args...), ArgumentTuple &args)
{
    return Apply<R>( obj, f, args, std::index_sequence_for<Args...>{});
}


// LAST PART: glue everything together in a single function. 
#define BIND_MEMBER_FUNCTION( class_, memberfunc_)                  \
    PyObject *Call##class_##memberfunc_( class_ *self, PyObject *args)\
    {                                                               \
        /* no error checking whatsoever: "exercise for the reader"*/\
        auto arguments = FillTuple( args, &class_::memberfunc_);    \
        /* deal with void-returning functions: yet another EFTR */  \
        return Py_BuildValue(                                       \
            GetReturnFormat( &class_::memberfunc_).c_str(),         \
            Apply( *self, &class_::memberfunc_, arguments));        \
    }                                                               \
    /**/

BIND_MEMBER_FUNCTION( Duck, MemberFunc);

我不打算使用第三方图书馆,但我现在没有任何线索。你能告诉我大概的实现步骤吗?我不太明白voidint[]{0,strm@Jerry,这是一个C++11/C++14技巧,用于编写接近折叠表达式的内容。在C++17中,您可以将其作为strm编写。我在PyArg_ParseTuple obj中发现了get参数…在PyArg_ParseTuple obj中,GetArgumentFormats f.C_str,get arguments…;导致程序崩溃,但我手动将其测试为int a,b;PyArg_ParseTupleobject,ii,&a,&b;一切正常。问题已解决,需要更改以获取参数(&G)。。。。