Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/155.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++ 将类方法作为void函数指针传递(C+;+;11)_C++_C++11 - Fatal编程技术网

C++ 将类方法作为void函数指针传递(C+;+;11)

C++ 将类方法作为void函数指针传递(C+;+;11),c++,c++11,C++,C++11,我有一个对象,它需要与现有的C api接口来注册一个in中断(不带参数的void函数)。我可以将中断附加到函数function()。但是,我希望能够将参数传递给函数,但这会更改函数签名。我认为一种解决方法是创建一个对象来存储参数(并根据需要修改它们),然后传入一个方法(或类似方法)。然而,我还没有弄明白如何做到这一点 我试着以[=](){std::cout的形式传入一个lambda,因此您希望为不同的中断注册一个相同的中断处理程序,每个中断都具有相同但独立的数据 使用静态数据的独立模板函数怎么样

我有一个对象,它需要与现有的C api接口来注册一个in中断(不带参数的void函数)。我可以将中断附加到函数
function()
。但是,我希望能够将参数传递给函数,但这会更改函数签名。我认为一种解决方法是创建一个对象来存储参数(并根据需要修改它们),然后传入一个方法(或类似方法)。然而,我还没有弄明白如何做到这一点


我试着以
[=](){std::cout的形式传入一个lambda,因此您希望为不同的中断注册一个相同的中断处理程序,每个中断都具有相同但独立的数据

使用静态数据的独立模板函数怎么样

template <unsigned int IRQ>
void irqHandler()
{
    static A a(IRQ);
    a.doSomething();
};

void(*interruptVectorTable[12])() =
{
   // ...
   &irqHandler<7>,
   // ...
   &irqHandler<10>,
};
模板
void irqHandler()
{
静态A(IRQ);
a、 doSomething();
};
void(*可中断的[12])()=
{
// ...
&irqHandler,
// ...
&irqHandler,
};

因此,您希望为不同的中断注册一个相同的中断处理程序,每个中断都具有相同但独立的数据

使用静态数据的独立模板函数怎么样

template <unsigned int IRQ>
void irqHandler()
{
    static A a(IRQ);
    a.doSomething();
};

void(*interruptVectorTable[12])() =
{
   // ...
   &irqHandler<7>,
   // ...
   &irqHandler<10>,
};
模板
void irqHandler()
{
静态A(IRQ);
a、 doSomething();
};
void(*可中断的[12])()=
{
// ...
&irqHandler,
// ...
&irqHandler,
};

这是一种非常复杂的方法。它需要一些样板代码,所以我将其包装在几个宏中(糟糕)。对于
C++11
来说,锁定有些有限(读取效率较低),但如果您可以访问
C++14
或更高版本,则可以改进:

// ## Header Library Code

namespace static_dispatch {

inline std::mutex& mutex()
    { static std::mutex mtx; return mtx; }

inline std::lock_guard<std::mutex> lock_for_reading()
    { return std::lock_guard<std::mutex>(mutex()); }

inline std::lock_guard<std::mutex> lock_for_updates()
    { return std::lock_guard<std::mutex>(mutex()); }

inline std::vector<void*>& cbdb()
{
    static std::vector<void*> vps;
    return vps;
}

inline void register_cb(void(*cb)(), void* user_data)
{
    auto lock = lock_for_updates();
    cbdb().push_back(user_data);
    cb(); // assign id under lock
}

inline void* retreive_cb(std::size_t id)
{
    auto lock = lock_for_reading();
    return cbdb()[id];
}

}  // namespace static_dispatch

#define CALLBACK_BOILERPLATE(id) \
    static auto id = std::size_t(-1); \
    if(id == std::size_t(-1)) { id = static_dispatch::cbdb().size() - 1; return; }

#define CALLBACK_RETREIVE_DATA(id, T) \
    reinterpret_cast<T*>(static_dispatch::retreive_cb(id))

// ## Application Code

class A
{
public:
    void member_callback_1() const
    {
        std::cout << s << '\n';
    }

private:
    std::string s = "hello";
};

void callback_1()
{
    CALLBACK_BOILERPLATE(id);

    auto a = CALLBACK_RETREIVE_DATA(id, A);

    a->member_callback_1();
}

// The framework that you need to register your 
// callbacks with
void framework_register(void(*cb)()) { cb(); }

int main()
{
    A a;

    // register callback with data structure
    static_dispatch::register_cb(&callback_1, &a);

    // Now register callback with framework because subsequent calls
    // will invoke the real callback.
    framework_register(&callback_1);

    // etc...
}

这是一种复杂的方法。它需要一些样板代码,所以我将其包装在两个宏中(糟糕)。对于
C++11
来说,锁定有些有限(读取效率较低),但如果您可以访问
C++14
或更高版本,则可以改进:

// ## Header Library Code

namespace static_dispatch {

inline std::mutex& mutex()
    { static std::mutex mtx; return mtx; }

inline std::lock_guard<std::mutex> lock_for_reading()
    { return std::lock_guard<std::mutex>(mutex()); }

inline std::lock_guard<std::mutex> lock_for_updates()
    { return std::lock_guard<std::mutex>(mutex()); }

inline std::vector<void*>& cbdb()
{
    static std::vector<void*> vps;
    return vps;
}

inline void register_cb(void(*cb)(), void* user_data)
{
    auto lock = lock_for_updates();
    cbdb().push_back(user_data);
    cb(); // assign id under lock
}

inline void* retreive_cb(std::size_t id)
{
    auto lock = lock_for_reading();
    return cbdb()[id];
}

}  // namespace static_dispatch

#define CALLBACK_BOILERPLATE(id) \
    static auto id = std::size_t(-1); \
    if(id == std::size_t(-1)) { id = static_dispatch::cbdb().size() - 1; return; }

#define CALLBACK_RETREIVE_DATA(id, T) \
    reinterpret_cast<T*>(static_dispatch::retreive_cb(id))

// ## Application Code

class A
{
public:
    void member_callback_1() const
    {
        std::cout << s << '\n';
    }

private:
    std::string s = "hello";
};

void callback_1()
{
    CALLBACK_BOILERPLATE(id);

    auto a = CALLBACK_RETREIVE_DATA(id, A);

    a->member_callback_1();
}

// The framework that you need to register your 
// callbacks with
void framework_register(void(*cb)()) { cb(); }

int main()
{
    A a;

    // register callback with data structure
    static_dispatch::register_cb(&callback_1, &a);

    // Now register callback with framework because subsequent calls
    // will invoke the real callback.
    framework_register(&callback_1);

    // etc...
}

你将无法绕过
std::bind()
。模板化方法将作为静态方法工作,但实际上它与模板化自由函数相同。这就足够了吗?模板化方法中的
a
无论如何都不是类成员
a
。你将无法绕过
std::bind()
。模板化方法可以像静态的一样工作,但实际上它与模板化的自由函数是一样的。这就足够了吗?模板化方法中的
a
不是类成员
a
。谢谢!这个解决方案工作得很好。我用受此启发的解决方案修改了我的问题。谢谢!这个解决方案是可行的好吧,我用我的解决方案修改了我的问题,这就是我的灵感所在。
inline std::shared_timed_mutex& mutex()
    { static std::shared_timed_mutex mtx; return mtx; }

inline std::shared_lock<std::shared_timed_mutex> lock_for_reading()
    { return std::shared_lock<std::shared_timed_mutex>(mutex()); }

inline std::unique_lock<std::shared_timed_mutex> lock_for_updates()
    { return std::unique_lock<std::shared_timed_mutex>(mutex()); }