在 libclang 访问者中将成员函数作为参数传递
pass a member function as argument in libclang visitor
我正在使用 LibClang 在 C++ 程序中遍历 AST,如下所示:
CXChildVisitResult visitor(CXCursor cursor, CXCursor parent, CXClientData data) {
// some code
}
int main() {
// some code
clang_visitChildren(rootCursor, visitor, 0);
}
如果 visitor()
是 class 的成员,我不知道如何将 visitor
传递给 clang_visitChildren()
。我尝试使用 ClassName::visitor
而不是访问者,但出现以下编译器错误:
error: invalid use of non-static member function ‘CXChildVisitResult ClassName::visitor(CXCursor, CXCursor, CXClientData)’
clang_visitChildren
只接受常规函数,不接受成员函数。它为了使用一个成员函数,你必须创建一个辅助静态成员函数来调用一个非静态成员函数:
class MyVisitor
{
public:
CXChildVisitResult visitor(CXCursor, CXCursor);
static CXChildVisitResult visitorHelper(CXCursor cursor, CXCursor parent, CXClientData client_data) {
return static_cast<MyVisitor *>(client_data)->visitor(cursor, parent);
}
};
int main() {
MyVisitor myVisitor;
// some code
clang_visitChildren(rootCursor, &MyVisitor::visitorHelper, &myVisitor);
}
请注意使用 client_data
参数将指针传递给要调用其方法的对象。这是 C API.
中非常常见的回调模式
或者,您可能想要选择一个不同的库来使用 Clang(更多信息 here) such as LibTooling,它提供了一个 C++ 接口。
将成员函数作为参数传递很容易。诀窍是语法。您不需要静态函数,您需要一个指向成员函数的指针和一个指向调用对象的指针。
看这个例子
#include <iostream>
using namespace std;
class Foo {
public:
virtual void MemberFunc() {
std::cout << "MemberFunc called" << std::endl;
}
virtual void MemberFuncWithArgs(int a, std::string b, double c) {
std::cout << "MemberFuncWithArgs called with a = " << a << " b = " << b << " c = " << c << std::endl;
}
};
class Bar : public Foo {
public:
virtual void MemberFunc() {
std::cout << "Bar MemberFunc called" << std::endl;
}
};
// funPtr is a pointer to the function in the class Foo:: scope that takes zero arguments and returns void
void CallClassFunction(void (Foo::*funPtr)(), Foo* obj) {
// We deference the function pointer and invoke it on the caller
(obj->*funPtr)();
}
// Same as above but funPtr takes 3 arguments
void CallClassFunctionWithArgs(void (Foo::*funPtr)(int a, std::string b, double c), int a, std::string b, double c, Foo* obj) {
(obj->*funPtr)(a, b, c);
}
int main()
{
cout<<"Hello World";
Foo obj;
// We take the address of the class member function (makes a pointer)
// We take a pointer to the obj variable
CallClassFunction(&Foo::MemberFunc, &obj);
CallClassFunctionWithArgs(&Foo::MemberFuncWithArgs, 34, "hello", 65.87, &obj);
// Works with inheritance too! This will now call Bar::MemberFunc
Bar bar;
CallClassFunction(&Foo::MemberFunc, &bar);
return 0;
}
我正在使用 LibClang 在 C++ 程序中遍历 AST,如下所示:
CXChildVisitResult visitor(CXCursor cursor, CXCursor parent, CXClientData data) {
// some code
}
int main() {
// some code
clang_visitChildren(rootCursor, visitor, 0);
}
如果 visitor()
是 class 的成员,我不知道如何将 visitor
传递给 clang_visitChildren()
。我尝试使用 ClassName::visitor
而不是访问者,但出现以下编译器错误:
error: invalid use of non-static member function ‘CXChildVisitResult ClassName::visitor(CXCursor, CXCursor, CXClientData)’
clang_visitChildren
只接受常规函数,不接受成员函数。它为了使用一个成员函数,你必须创建一个辅助静态成员函数来调用一个非静态成员函数:
class MyVisitor
{
public:
CXChildVisitResult visitor(CXCursor, CXCursor);
static CXChildVisitResult visitorHelper(CXCursor cursor, CXCursor parent, CXClientData client_data) {
return static_cast<MyVisitor *>(client_data)->visitor(cursor, parent);
}
};
int main() {
MyVisitor myVisitor;
// some code
clang_visitChildren(rootCursor, &MyVisitor::visitorHelper, &myVisitor);
}
请注意使用 client_data
参数将指针传递给要调用其方法的对象。这是 C API.
或者,您可能想要选择一个不同的库来使用 Clang(更多信息 here) such as LibTooling,它提供了一个 C++ 接口。
将成员函数作为参数传递很容易。诀窍是语法。您不需要静态函数,您需要一个指向成员函数的指针和一个指向调用对象的指针。
看这个例子
#include <iostream>
using namespace std;
class Foo {
public:
virtual void MemberFunc() {
std::cout << "MemberFunc called" << std::endl;
}
virtual void MemberFuncWithArgs(int a, std::string b, double c) {
std::cout << "MemberFuncWithArgs called with a = " << a << " b = " << b << " c = " << c << std::endl;
}
};
class Bar : public Foo {
public:
virtual void MemberFunc() {
std::cout << "Bar MemberFunc called" << std::endl;
}
};
// funPtr is a pointer to the function in the class Foo:: scope that takes zero arguments and returns void
void CallClassFunction(void (Foo::*funPtr)(), Foo* obj) {
// We deference the function pointer and invoke it on the caller
(obj->*funPtr)();
}
// Same as above but funPtr takes 3 arguments
void CallClassFunctionWithArgs(void (Foo::*funPtr)(int a, std::string b, double c), int a, std::string b, double c, Foo* obj) {
(obj->*funPtr)(a, b, c);
}
int main()
{
cout<<"Hello World";
Foo obj;
// We take the address of the class member function (makes a pointer)
// We take a pointer to the obj variable
CallClassFunction(&Foo::MemberFunc, &obj);
CallClassFunctionWithArgs(&Foo::MemberFuncWithArgs, 34, "hello", 65.87, &obj);
// Works with inheritance too! This will now call Bar::MemberFunc
Bar bar;
CallClassFunction(&Foo::MemberFunc, &bar);
return 0;
}