1

我正在尝试为 GNU Readline 编写一个 c++ 包装器,以便能够轻松使用自定义完成,但遇到了一个小问题并且想不出解决方案(我还是 c++ 新手)。

class ReadLine {

public:

    ReadLine();
    ~ReadLine();

    std::string exec ();
    void enableHistory ();

private:
    std::vector<std::string> keywordList;
    bool history;

private:
    static char** my_completion (const char*, int, int);
    void* xmalloc (int);

    char* generator (const char*, int);
    char* dupstr (std::string);

};

cpp文件:

std::string ReadLine::exec(){

    rl_attempted_completion_function = my_completion;

    std::string buf = "";

    buf = readline("Command>>");
    //enable auto-complete
    rl_bind_key('\t',rl_complete);

    if (buf[0]!=0)
        add_history(buf.c_str());

    return buf;
}




char** ReadLine::my_completion (const char* text, int start, int end) {


    char** matches;

    matches = NULL;

    if (start == 0) 
        matches = rl_completion_matches(text, my_generator);

    return matches;


}

我的问题是线路

匹配 = rl_completion_matches(文本,my_generator)

它显然会抛出一个错误:call to non-static member function without an object argument但我不想让生成器成为静态的并且我找不到它应该采用什么参数,因为我将无法访问其中的类成员(我需要关键字列表来生成关键字)。

你有什么建议?

4

1 回答 1

0

以一种好的方式解决这个问题并不容易,因为正常的解决方案是通过使用静态包装函数来解决它,在该函数中,您将指向类的指针作为参数传递。

其他人可能会想出更好的东西,但我认为解决方案是有一个全局变量,它是指向当前 ReadLine 类实例的指针 - 这可能是一个堆栈,所以你可以将一个新的压入它,然后在完成后弹出它以返回旧的。

在简单的情况下,你会有这样的事情:

ReadLine *currenReadLine = 0;

.... 

std::string ReadLine::exec(){
   ... 
   currentReadLine = this;
}


// declared as static in the class.
char ** ReadLine::my_completion(...)
{
    return currentReadLine->actual_completion(...);
}

和类似的解决方案my_generator

于 2013-08-05T08:42:47.943 回答