передать функцию-член в качестве аргумента посетителю libclang - PullRequest
0 голосов
/ 17 октября 2018

Я использую LibClang для обхода AST в программе на C ++, как показано ниже:

CXChildVisitResult visitor(CXCursor cursor, CXCursor parent, CXClientData data) {
  // some code
}

int main() {
  // some code
  clang_visitChildren(rootCursor, visitor, 0);
}

Я не знаю, как передать visitor в clang_visitChildren(), если visitor() является членом класса,Я попытался использовать ClassName::visitor вместо посетителя, но получаю следующую ошибку компилятора:

error: invalid use of non-static member function ‘CXChildVisitResult ClassName::visitor(CXCursor, CXCursor, CXClientData)’

Ответы [ 2 ]

0 голосов
/ 17 октября 2018

Передача функций-членов в качестве аргументов проста.Хитрость в синтаксисе.Вам не нужны статические функции, вам нужен указатель на функцию-член и указатель на вызывающий объект.

См. Этот пример

#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;
}
0 голосов
/ 17 октября 2018

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 (дополнительная информация здесь ), например LibTooling который обеспечивает интерфейс C ++.

...