Protected methods

161 views
Skip to first unread message

Michael Kirsch

unread,
Aug 31, 2012, 11:18:21 AM8/31/12
to lqt-bi...@googlegroups.com
Why aren't protected methods like QWidget::resizeEvent available? I looked at the source and I don't see why.

Michael Kirsch

unread,
Sep 2, 2012, 5:30:09 PM9/2/12
to lqt-bi...@googlegroups.com
I modified lqt to expose protected methods (and possibly some other improvements):


I had to replace the ordinary wrapper functions with static methods of a class derived from the class that the wrapped method belongs to. This allows it to access protected methods.

Michal Kottman

unread,
Sep 3, 2012, 4:39:11 AM9/3/12
to lqt-bi...@googlegroups.com
This enables public access from Lua to all protected methods, am I
correct? Lqt already has a simple principle how to
access the parent protected method you are overriding using a hack -
error(SUPER).

Could you add a few Lua tests demonstrating what you can do with this approach?

Michael Kirsch

unread,
Sep 3, 2012, 9:01:43 AM9/3/12
to lqt-bi...@googlegroups.com
On Monday, September 3, 2012 4:39:32 AM UTC-4, Michal Kottman wrote

This enables public access from Lua to all protected methods, am I
correct?

Yes, but I don't really have a problem with that, since Lua doesn't have the concept of private/protected/public. I think it's better to trust the programmer not to use them poorly than to be missing functionality.
 
Lqt already has a simple principle how to
access the parent protected method you are overriding using a hack -
error(SUPER).

But that's just a really ugly hack, and it doesn't let you run code *after* calling the base implementation.
 
Could you add a few Lua tests demonstrating what you can do with this approach?

I'm working on an auto-scrolling QTextEdit example that makes use of it, and is as far as I can tell impossible to properly implement in the normal lqt. The problem is that conecting signals to functions if kind of broken, and often gives errors like these:

    Object::connect: No such slot QScrollBar::LQT_SLOT_1(int)

Am I doing something wrong? I found the connect source code, and can't figure out why it would fail like this.

Another thing is that, for example, "QTextEdit.resizeEvent", works, but "QTextBrowser.resizeEvent" doesn't. Does lqt not support looking in base classes if lookup fails?

I am also working on improving connect to accept "methods" of Lua "objects":

    myqobject:connect('2some_signal(int)', myobject, myobject.mymethod)

This will call <myobject.mymethod>(<myobject>, <signal args>) when the signal is emitted.

And finally, there's another big problem in lqt that I would like to mention: the way it handles enums. It converts them to and from strings, but not everywhere. In places where it doesn't, the constants aren't available, so I have to hardcode the numbers. Why not just throw away the idea of using strings for enums, and expose the constants (like Qt.DisplayRole == 0, for example) directly to Lua?

I know this would break existing lqt programs, but IMO it would be a huge improvement that would be worth it when writing new programs.

Michal Kottman

unread,
Sep 3, 2012, 4:35:42 PM9/3/12
to lqt-bi...@googlegroups.com
On 3 September 2012 15:01, Michael Kirsch <mkirs...@gmail.com> wrote:
> On Monday, September 3, 2012 4:39:32 AM UTC-4, Michal Kottman wrote
>>
>>
>> This enables public access from Lua to all protected methods, am I
>> correct?
>
>
> Yes, but I don't really have a problem with that, since Lua doesn't have the
> concept of private/protected/public. I think it's better to trust the
> programmer not to use them poorly than to be missing functionality.

I agree, I was just asking :)

>> Lqt already has a simple principle how to
>> access the parent protected method you are overriding using a hack -
>> error(SUPER).
>
>
> But that's just a really ugly hack, and it doesn't let you run code *after*
> calling the base implementation.

True, even the commit of this function says it is a hack :)

>> Could you add a few Lua tests demonstrating what you can do with this
>> approach?
>
> I'm working on an auto-scrolling QTextEdit example that makes use of it, and
> is as far as I can tell impossible to properly implement in the normal lqt.
> The problem is that conecting signals to functions if kind of broken, and
> often gives errors like these:
>
> Object::connect: No such slot QScrollBar::LQT_SLOT_1(int)

How are you calling this? That may be important, this is the first
time I actually see this kind of error. My guess is that you are
trying to create the slot on an object that was not created by Lua
(QScrollBar.new).

> Am I doing something wrong? I found the connect source code, and can't
> figure out why it would fail like this.

The source code (the creation of given scroll bar, and the actual
call) would be helpful to find out what is happening.

> Another thing is that, for example, "QTextEdit.resizeEvent", works, but
> "QTextBrowser.resizeEvent" doesn't. Does lqt not support looking in base
> classes if lookup fails?

Yes it does, in this case I am not sure what exactly causes the
problem, but in "base lqt" QTextEdit.resizeEvent does not exist, so
QTextBrowser.resizeEvent should neither. Also, inheritance is
implemented on objects, not on classes. Therefore if you have:

local tb = QTextBrowser()
print(tb.alignment) -- function: 0xXXXXXXXX
print(QTextBrowser.alignment) -- nil

Note that on my installation, tb.resizeEvent is also nil.

> I am also working on improving connect to accept "methods" of Lua "objects":
>
> myqobject:connect('2some_signal(int)', myobject, myobject.mymethod)
>
> This will call <myobject.mymethod>(<myobject>, <signal args>) when the
> signal is emitted.

This was supposed to work by using closures instead:

myobject:connect('2somesignal(int)', function(...)
myobject:mymethod(...) end)

Note that you cannot use signatures not already available in existing
signals - this means that you cannot create new signal signatures
(there is one big class called SlotAcceptor which implements all known
slot signatures and dispatches to Lua).

> And finally, there's another big problem in lqt that I would like to
> mention: the way it handles enums. It converts them to and from strings, but
> not everywhere. In places where it doesn't, the constants aren't available,
> so I have to hardcode the numbers. Why not just throw away the idea of using
> strings for enums, and expose the constants (like Qt.DisplayRole == 0, for
> example) directly to Lua?

They already exist like numbers, but they are one level deep -
Qt.ItemDataRole.DisplayRole == 0

To search for such names - look at documentation (see the enum name),
or this in Lua:

for k,v in pairs(Qt) do for kk,vv in pairs(v) do if kk ==
'DisplayRole' then print(k, kk, vv) end end end

> I know this would break existing lqt programs, but IMO it would be a huge
> improvement that would be worth it when writing new programs.

The longer I think about it, the more I am assured of the fact that
Lqt needs a complete reimplementation (but minimizing the differences
from script size).

Michael Kirsch

unread,
Sep 3, 2012, 5:23:19 PM9/3/12
to lqt-bi...@googlegroups.com


On Monday, September 3, 2012 4:36:03 PM UTC-4, Michal Kottman wrote:
How are you calling this? That may be important, this is the first
time I actually see this kind of error. My guess is that you are
trying to create the slot on an object that was not created by Lua
(QScrollBar.new).

That's correct, the object was not created by Lua (I accessed it with edit:verticalScrollBar()). 

The source code (the creation of given scroll bar, and the actual
call) would be helpful to find out what is happening.

Here is is:

======================================================

    require 'qtcore'
    require 'qtgui'

    local app = QApplication(0, {})

    local edit = QTextEdit()

    edit:setVerticalScrollBarPolicy('ScrollBarAlwaysOn')
    edit:setHorizontalScrollBarPolicy('ScrollBarAlwaysOff')

    edit.atbottom = true
    edit.vsb = edit:verticalScrollBar()

    edit:connect('2textChanged()', function (_)
        if edit.atbottom then edit.vsb:setValue(edit.vsb:maximum()) end
    end)

    edit.vsb:connect('2valueChanged(int)', function (_, newpos)
        edit.atbottom = newpos == edit.vsb:maximum()
    end)

    function edit.resizeEvent(_, event)
        QTextEdit.resizeEvent(edit, event)
        if edit.atbottom then edit.vsb:setValue(edit.vsb:maximum()) end
    end

    local cur = QTextCursor(edit:document())

    local timer = QTimer()
    timer:setInterval(100)
    local count = 1
    timer:connect('2timeout()', function ()
        cur:insertText(tostring(count)..'\n')
        count = count + 1
    end)
    timer:start()

    edit:show()

    app.exec()

======================================================
 
This was supposed to work by using closures instead:

    myobject:connect('2somesignal(int)', function(...)
myobject:mymethod(...) end)

I thought that my idea would be cleaner, since it's a common thing to do and was quite simple to implement.

    myobject:connect('2somesignal(int)', function (...) myobject:mymethod(...) end)

vs.

    myobject:connect('2somesignal(int)', myobject, myobject.mymethod)

Note that you cannot use signatures not already available in existing
signals - this means that you cannot create new signal signatures
(there is one big class called SlotAcceptor which implements all known
slot signatures and dispatches to Lua).

I don't really understand. I'm not really familiar with how signals and slots work, is there any good place to find out?
 
They already exist like numbers, but they are one level deep -
Qt.ItemDataRole.DisplayRole == 0

OK, I expected it to work like it does in C++.
 
The longer I think about it, the more I am assured of the fact that
Lqt needs a complete reimplementation (but minimizing the differences
from script size).

I was thinking about that too, I once tried making a simple and compact tool (it's just a single Lua script and a C++ header, you write a configuration file in Lua, the script takes it and writes a C++ file, and that C++ file can be compiled with the header to produce a module.) for binding C++ functions to Lua, maybe I can try to finish it up and add features like wrapper classes to reimplement virtual methods in Lua.

Maybe it would be a good idea to just make lqt turn the XML into a config file for it, and then use it to make the bindings?

Michael Kirsch

unread,
Sep 13, 2012, 7:24:13 PM9/13/12
to lqt-bi...@googlegroups.com
On Monday, September 3, 2012 5:23:19 PM UTC-4, Michael Kirsch wrote:
The longer I think about it, the more I am assured of the fact that
Lqt needs a complete reimplementation (but minimizing the differences
from script size).

I was thinking about that too, I once tried making a simple and compact tool (it's just a single Lua script and a C++ header, you write a configuration file in Lua, the script takes it and writes a C++ file, and that C++ file can be compiled with the header to produce a module.) for binding C++ functions to Lua, maybe I can try to finish it up and add features like wrapper classes to reimplement virtual methods in Lua.

Maybe it would be a good idea to just make lqt turn the XML into a config file for it, and then use it to make the bindings?

I was trying to do that for the last few days, and just ran into a big problem: the XML file doesn't contain the class QMetaObject. Any idea how to fix that?

But anyway, it successfully generates the code to bind QPoint now:

> QtCore = require 'QtCore'
> =QtCore.QPoint
table: 0x19ba120
> p = QtCore.QPoint()
> =p:x()
0
> return p.x()
stdin:1: improper method args
stack traceback:
[C]: in function 'x'
stdin:1: in main chunk
[C]: ?
> =p:isNull()
true
> p:setX(4)
> return p:isNull()
false
> =p:x()
4

Gedalia Pasternak

unread,
Mar 8, 2013, 11:47:40 AM3/8/13
to lqt-bi...@googlegroups.com
Hi I just got latest after a long time and tried to build with
vc10 qt 4.7.3
I've hit a couple of issues, while I think I have QT_STL support set to true the preprocessor won't compile due to use of fromStdString and toStdString. I've worked around this, but it seems odd.

More problematic is I've got thousands of unresolved externals:
1>qtcore_merged_build.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: virtual void __thiscall QThread::run(void)" (__imp_?run@QThread@@UAEXXZ) referenced in function "int __cdecl lqt_bind_10968(struct lua_State *)" (?lqt_bind_10968@@YAHPAUlua_State@@@Z)
1>qtcore_merged_build.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: void __thiscall QThread::started(void)" (__imp_?started@QThread@@QAEXXZ) referenced in function "int __cdecl lqt_bind_10965(struct lua_State *)" (?lqt_bind_10965@@YAHPAUlua_State@@@Z)
1>qtcore_merged_build.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: static void __cdecl QThread::sleep(unsigned long)" (__imp_?sleep@QThread@@SAXK@Z) referenced in function "int __cdecl lqt_bind_10972(struct lua_State *)" (?lqt_bind_10972@@YAHPAUlua_State@@@Z)
1>qtcore_merged_build.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: int __thiscall QThread::exec(void)" (__imp_?exec@QThread@@QAEHXZ) referenced in function "int __cdecl lqt_bind_10969(struct lua_State *)" (?lqt_bind_10969@@YAHPAUlua_State@@@Z)
1>qtcore_merged_build.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: static void __cdecl QThread::msleep(unsigned long)" (__imp_?msleep@QThread@@SAXK@Z) referenced in function "int __cdecl lqt_bind_10974(struct lua_State *)" (?lqt_bind_10974@@YAHPAUlua_State@@@Z)

I think these might be protected/static functions, has anyone seen this before?
thanks
Gedalia

Michal Kottman

unread,
Mar 8, 2013, 1:33:40 PM3/8/13
to lqt-bi...@googlegroups.com
On 8 March 2013 17:47, Gedalia Pasternak <ged...@gmail.com> wrote:
> Hi I just got latest after a long time and tried to build with
> vc10 qt 4.7.3

> More problematic is I've got thousands of unresolved externals:
> 1>qtcore_merged_build.obj : error LNK2019: unresolved external symbol
> "__declspec(dllimport) public: virtual void __thiscall QThread::run(void)"
> (__imp_?run@QThread@@UAEXXZ) referenced in function "int __cdecl
> lqt_bind_10968(struct lua_State *)" (?lqt_bind_10968@@YAHPAUlua_State@@@Z)
>
> I think these might be protected/static functions, has anyone seen this
> before?

Unfortunately, protected methods cannot be enabled in VisualC++. The
reason is that the visibility of a given method is a part of the
mangling scheme. Therefore, when I do the 'protected' -> 'public'
preprocessing trick, the mangled name changes and the linker cannot
find the given symbol.

For this reason VC is currently unsupported, only MinGW works on
Windows. If you need a working build, please use a prior version, or
use the binaries available at
https://dl.dropbox.com/u/11514376/lqt/lqt_4.8.4_lfw_binaries.zip
compiled by MinGW and conveniently distributed with corresponding Qt
binaries.

Gedalia Pasternak

unread,
Mar 8, 2013, 1:55:18 PM3/8/13
to lqt-bi...@googlegroups.com
What's the best way to get the prior build? I just grabbed the git hub latest revision. I've got my own custom qt DLL's so I can't really use prebuilt stuff.
You might want to add some CMake warning that VS is broken (or disable problematic code with a compiler aware #define)
thanks
-Gedalia



--

---
You received this message because you are subscribed to the Google Groups "lqt-bindings" group.
To unsubscribe from this group and stop receiving emails from it, send an email to lqt-bindings...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.





--
---------------------------------------------------------------
cel: 917.776.8346                 AIM: gedaliap
http://www.gedalia.net
---------------------------------------------------------------
Fight Entropy!!!  Fight Entropy!!!  Figth Etnropy! !
iFgth Etnrop!y ! giFth tErno!py !  giFt htrEno!p y! --- Well maybe
not...

Michal Kottman

unread,
Mar 8, 2013, 1:59:11 PM3/8/13
to lqt-bi...@googlegroups.com
On 8 March 2013 19:55, Gedalia Pasternak <ged...@gmail.com> wrote:
> What's the best way to get the prior build? I just grabbed the git hub
> latest revision. I've got my own custom qt DLL's so I can't really use
> prebuilt stuff.

A simple "git checkout HEAD~" will take you to the previous commit
that worked. I should probably tag those.

> You might want to add some CMake warning that VS is broken (or disable
> problematic code with a compiler aware #define)

Yes, well, a lot of things should be done, unfortunately I have too
little time for this project...
Reply all
Reply to author
Forward
0 new messages