[lldb-dev] small Editline wrapper cleanup req for feedback
Greg Clayton via lldb-dev
lldb-dev at lists.llvm.org
Tue May 4 14:42:43 PDT 2021
As long as the solution matches "EditLine *" (C struct type from edit line library) to back to the C++ instance of "Editline" (lower case ell in "line" from LLDB). It should be easy to do with a template.
I am fine with any new solution that makes it easier to add new commands. I would rather have a templated function argument over a template argument if possible. I am thinking of something like:
createEditLineCommandDescriptor(“Command1", “Command1 help", &Foo::Foo1);
createEditLineCommandDescriptor(“Command2", “Command2 help", &Foo::Bar);
as I find it more readable.
Greg
> On Apr 30, 2021, at 9:35 PM, Neal Sidhwaney via lldb-dev <lldb-dev at lists.llvm.org> wrote:
>
> Some comments in https://reviews.llvm.org/rGfd89af6880f33ead708abe2f7d88ecb687d4e0d2 <https://reviews.llvm.org/rGfd89af6880f33ead708abe2f7d88ecb687d4e0d2> prompted me to look more into potential simplifications of our EditLine wrapper and I wanted to run this by anyone who is interested before making the changes.
>
> Right now we set a bunch of callbacks in libedit that are captureless lambdas implicitly converted to C function pointers. The lambdas look up an instance of our Editline class and invoke member functions. The boilerplate that could be generated by templates is something like the following:
>
> class Foo { // Imagine this is our Editline class that wraps libedit
> public:
> unsigned char Foo1(int ch) { // These are member functions invoked by lambdas we pass to libedit
> return 'a';
> }
> unsigned char Bar(int ch) {
> return 'b';
> }
> unsigned char Baz(int ch) {
> return 'c';
> }
> };
>
> typedef unsigned char (*elFnPtr)(EditLine*, int); // Signature of callbacks libedit takes (note Edit__L__ine is libedit, and Edit__l__ine is our wrapper)
> typedef unsigned char (Foo::*FooMemPtr)(int ch); // Signature of member functions invoked
>
> template<FooMemPtr callback, typename Fn = elFnPtr>
> tuple<const char*, const char*, Fn> createEditLineCommandDescriptor(const char* command, const char* helpText) {
> return make_tuple(command, helpText, [] (EditLine*, int ch) {
> cout << ch;
> Foo foo;
> ((&foo)->*callback)('a');
> return (unsigned char) ch;
> });
> }
>
> auto editlineCommands = {
> createEditLineCommandDescriptor<&Foo::Foo1>(“Command1", “Command1 help"),
> createEditLineCommandDescriptor<&Foo::Bar>(“Command2", “Command2 help")
> };
>
> for (auto editlineCommand : editLineCommands) {
> // call into libedit to add editlineCommand, e.g.:
> el_set(EL_ADDFN, editlineCommand.get<0>(), editLineCommand.get<1>(), editLineCommand.get<2>());
> }
>
> The pointer to member function is a type parameter because otherwise the compiler complains about the lambda needing to capture it, in which case we could not pass it to libedit.
>
> I also plan to look into the wchar_t/char preprocessor logic that the original comment brought up but then I got distracted by shiny template stuff ;-)
>
> Thanks!
>
> Neal
> _______________________________________________
> lldb-dev mailing list
> lldb-dev at lists.llvm.org
> https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/lldb-dev/attachments/20210504/1a1b0781/attachment.html>
More information about the lldb-dev
mailing list