2013-03-24 216 views
6

我试图使用类功能(中断服务例程),类成员函数指针

void (ClassName::*fp)(void)=ClassName::FunctionName; 

并将其附加到一个Arduino中断引脚使用具有以下类型输入的功能,但其不工作。

void attachInterrupt(int, void (*)(void),int); 

我该如何做到这一点?中断服务例程(ISR)需要访问privat对象数据,所以我不能在类之外创建一个函数。

我的编译器错误:

注:我在寻找类中的解决方案,将接受表明我一个解决方案或显示我这是不可能的答案。

+2

你得到一个错误。它有什么错误? – 0x499602D2 2013-03-24 14:30:01

+0

我正在使用Visual Studio 2012编译器。我会把编译器错误置于我的问题中。 – 2013-03-24 14:31:36

+0

抱歉,错误的编译器错误一开始,现在它的权利 – 2013-03-24 14:41:34

回答

6

如果该函数不是static,则不能将其输入传递给接受非成员函数指针的函数。

考虑到一个非static成员函数有一个暗指向ClassName的指针作为它的第一个参数,它指向了调用成员函数的对象。

struct X 
{ 
    static void foo() { } // Does not have an implicit "this" pointer argument 
    void bar() { } // Has an implicit "this" pointer argument 
}; 

int main() 
{ 
    void (*f)() = &X::foo; // OK: foo is static 
    void (*g)() = &X::bar; // ERROR! bar is non-static 
} 

在这里,甚至没有std::bind()会的工作,因为结果是无法转换为一个函数指针。 Lambdas可以转换为函数指针,但前提是它们不捕获(而且这里的lambda需要捕获该对象来调用成员函数)。

因此,唯一的(丑陋的)解决方法是具有全局适配器函数,该函数在通过全局指针变量可用的对象上调用成员函数。

struct X 
{ 
    void bar() { } 
}; 

void function_taking_a_function_pointer(void (*f)()) 
{ 
    // Do something... 
    f(); 
} 

X* pX = nullptr; 
void bar_adapter() 
{ 
    pX->bar(); 
} 

int main() 
{ 
    X x; // Some object I want to invoke the member function bar() on... 

    pX = &x; // Set the global pointer and invoke the function... 
    function_taking_a_function_pointer(bar_adapter); 
} 

如果你愿意,你可以让这个稍微灵活转动bar_adapter成函数模板,并通过指针到成员函数:全局指针变量调用函数之前设置作为一个模板参数:

template<typename T, void (T::*mf)()> 
void adapter() 
{ 
    (pX->*mf)(); 
} 

这里是你会怎么使用它:最后

#include <iostream> 

struct X 
{ 
    void foo() { std::cout << "X::foo()" << std::endl; } 
    void bar() { std::cout << "X::bar()" << std::endl; } 
}; 

void function_taking_a_function_pointer(void (*f)()) 
{ 
    // Do something... 
    f(); 
} 

X* pX = nullptr; 

template<typename T, void (T::*mf)()> 
void adapter() 
{ 
    (pX->*mf)(); 
} 

int main() 
{ 
    X x; // Some object I want to invoke the member function bar() on... 

    pX = &x; // Set the global pointer and invoke the function(s)... 

    function_taking_a_function_pointer(adapter<X, &X::foo>); 
    function_taking_a_function_pointer(adapter<X, &X::bar>); 
} 

,她e是live example

+0

谢谢,非常翔实的答案。 – 2013-03-24 14:58:45

+0

@FlyingSwissman:很高兴能帮到 – 2013-03-24 14:59:33

2

每个类成员函数都有一个隐含的第一个参数,即this指针,因此您的方法实际上并不包含void paramter list - 它只接受一个参数 - 它被调用的实例。

+0

好的,谢谢,这是有道理的,但不能解决我的问题。我能做的唯一事情就是公开对象数据并在对象之外创建一个ISR?还是有工作? – 2013-03-24 14:39:08

+0

@AndyProwl好点。谢谢 – 2013-03-24 14:49:20

+1

@FlyingSwissman:我在回答中提出了一个解决方法。不幸的是,当一个函数接受一个原始函数指针时,可以做的事情并不多。 – 2013-03-24 14:51:14

0

您可以使用boost::function<>boost::bind<>指向一个类的成员函数:

# include <boost/function.hpp> 
# include <boost/bind.hpp> 
class FunctionClass { 
    private: 
     double a_; 
    public: 
     FunctionClass (const double & a): a_(a){} 
     double multWithA (const double & x) const { return a_*x;} 
     double operator()(const double & x) const { return a_*x;} 
}; 

FunctionClass myClass (2.0); 
double x = 12.0; 
boost :: function <double (FunctionClass *, double)> funcPtr , funcPtr1; 
funcPtr =& FunctionClass :: multWithA; 
funcPtr1 =& FunctionClass :: operator(); 

std :: cout << myClass . multWithA (x) << std :: endl; 
std :: cout << funcPtr (& myClass ,x) << std :: endl; 
std :: cout << funcPtr1 (& myClass ,x) << std :: endl; 

// Bind the function with the class instance 
boost :: function <double (double)> funcPtrNew ; 
funcPtrNew = boost :: bind (funcPtr ,& myClass ,_1); 
std :: cout << funcPtrNew (x) << std :: endl; 
+2

他不能,他必须传递一个void(*)(void)函数指针。 (我不是arduino库的忠实粉丝。) – ipc 2013-03-24 14:36:41

+0

@ipc也应该与void一起工作,为什么不呢? – 4pie0 2013-03-24 14:41:45

+1

因为他必须调用[void attachInterrupt(int,void(*)(void),int)](http://arduino.cc/en/Reference/AttachInterrupt)。 – ipc 2013-03-24 14:46:03