我正试图为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;
}
我的问题是线路
matches=rl_completion_matches(文本,my_generator)
它显然抛出了一个错误:call to non-static member function without an object argument
,但我不想让生成器成为静态的,我找不到它应该使用什么参数,因为我无法访问它内部的类成员(我需要关键字列表来生成关键字)。
你有什么建议?
用一种好的方法解决这个问题并不容易,因为正常的解决方案是通过使用静态包装器函数来解决它,在该函数中,您将指向类的指针作为参数传入。
其他人可能会想出更好的方法,但我认为解决方案是有一个全局变量,它是指向当前ReadLine类实例的指针——这可能是一个堆栈,所以你可以将一个新的堆栈推到它上,然后在完成后弹出它回到旧的堆栈。
在简单的情况下,你会有这样的东西:
ReadLine *currenReadLine = 0;
....
std::string ReadLine::exec(){
...
currentReadLine = this;
}
// declared as static in the class.
char ** ReadLine::my_completion(...)
{
return currentReadLine->actual_completion(...);
}
以及CCD_ 2的类似解决方案。