On Feb 14, 2005, at 3:06 PM, Chris Barker wrote:
Bob Ippolito wrote:On Feb 14, 2005, at 2:05 PM, Chris Barker wrote:Except that AnyGui was never a good idea. A wrapper around a wrapper around a wrapper around a ..... just too much!
While I agree with the assertion that a large part needs to be written in a lower level language, I don't agree that wrapping a wrapper is going to be a performance problem.
It's not so much performance as complexity and the lowest-common-denominator problem. I"m pretty sure AnyGui is dead now anyway, and I've written a couple longer rants about this, but consider this:
AnyGuiTK is a Python wrapper around a Python wrapper around another scripting language, around and extension written in C, which is wrapped about the X11 API, which is emulated on other platforms.
AnyGuiWx is a Python wrapper around a SWIG wrapper around a C++ toolkit that is a wrapper around a native GUI toolkit.
When there's a bug, you've got a lot of layers that may be responsible!
That happens anyway :) Only the AnyGui developers need to care about this. A typical user of wxPython isn't going to be able to track a bug down to Carbon any better than a hypothetical AnyGui user is going to be able to.
It comes down to why? AnyGui has a flawed reason for being. NO one should care what toolkit is underlying their app at the bottom. What they should care about is;
The API The Look and Feel The Features The Platform support
AnyGUI had some potential to improve the API of the underlying toolkits but that's it. It makes much more sense to just write a better API wrapper around a toolkit that meets your other needs.
And the API is the only one of those things that the underlying toolkit DOESN'T ultimately control! Though it of course can have a big influence w.r.t. thread safety and what should be asynchronous.
The only fundamental difference between AnyGui and wxPython is that wxPython has a lot of C++ code (re: wxWidgets) where AnyGui would have a lot of Python code and relatively little platform code.
Ideally I'd propose a design like this:
1. Low level C/ObjC/C++ implementation (probably the native platform's toolkit, but could be wxWidgets, Qt, etc.)
wouldn't it have to be it it were X-platform?
Well the difference is that a "native platform" could be either the actual platform toolkit, or something on top of said toolkit. For example, there's the Win32 API, and then anything on top of that (MFC, wxWidgets, etc.).
2. Thin Python FFI layer (i.e. ctypes or PyObjC -- ultimate flexibility, minimal non-Python code)
What's FFI ?
Foreign Function Interface
2.5. Mid-level Python layer if necessary for a sane implementation of the high-level (might be overkill for PyObjC given how similar Objective-C and Python are)
Good point. The better the API you're wrapping, the less need for this.
3. High level Python layer (exposes a nice interface for Python developers)
This sounds a lot like PythonCard, actually.
1) wxWidgets
2) SWIG--wxPython
2.5) Some of the stuff wxPython adds: better dynamic binding syntax, OGL, FloatCanvas, other high level widgets.
3) That's what PythonCard itself is.
Yeah, I think PythonCard has the right approach for the layers that they control (2.5-3). wxPython/wxWidgets is something that I'd have approached differently, though at the time the projects were started the methods they used were most certainly the best or near-best ways to do it.
Wrappers generated with tools such as SWIG, sip, bgen, and Boost Python could also fit in for layer 2 -- but I think that a runtime solution is going to be better in the long run.
hmm. Is it possible to have a run-time solution for the more static languages like C++?
If you can do it for C you can do it for C++. The problem is that C has very few calling convention standards where C++ is much less standardized (though this is settling a bit). At worst, you would have a "cpptypes" that could only do magic for code generated by a particular compiler (e.g. gcc 3.3). The largest difference between Objective-C and C is that Objective-C compiles lots of RTTI (runtime type information) and makes it available to the objects themselves. C doesn't do this at all, all you have is the symbols in the symbol table, you don't even know if they're functions or globals. C++ is a hybrid, where a lot of this type information is actually in the symbol table, but not so easily available at runtime. The approach that you take with ctypes for C is to convert a lot of information from the headers into Python syntax, C++ you would take *some* information from the headers and translate into Python syntax (I haven't studied C++ compilation enough to be able to say what the scope of "some" is), and in Objective-C you need extremely little information from the headers (just constants, global variables, and functions -- basically cruft from the subset of Objective-C that is C -- which is fortunately not that popular in Objective-C code).
=========== Objective-C ===========
% class-dump Foundation.framework/Foundation
// all the structure and union names and fields are tracked.. struct AEDesc { unsigned int descriptorType; struct OpaqueAEDataStorageType **dataHandle; };
// the protocols too @protocol NSCoding - (void)encodeWithCoder:(id)fp8; - (id)initWithCoder:(id)fp8; @end
// and the classes @interface NSPlaceholderArray : NSArray { }
- (id)initWithObjects:(id *)fp8 count:(unsigned int)fp12; - (id)init; - (id)initWithContentsOfFile:(id)fp8; - (id)initWithContentsOfURL:(id)fp8; - (unsigned int)count; - (id)objectAtIndex:(unsigned int)fp8;
@end
= C =
% nm nm /usr/lib/libSystem.dylib
/usr/lib/libSystem.dylib(dylib1.o): # this is the name of the compilation unit from which it came
90057ca0 t ___initialize_Cplusplus # lots of symbols and addresses.. no metadata about them beyond their name
=== C++ ===
% nm libstdc++.a
libstdc++.a(bitset.o):
00000000 A _ZNKSt12_Base_bitsetILm1EE15_M_do_find_nextEmm.eh # really ugly names.. hmm!
00000000 A _ZNKSt12_Base_bitsetILm1EE16_M_do_find_firstEm.eh
0000005c T __ZNKSt12_Base_bitsetILm1EE15_M_do_find_nextEmm
% nm libstdc++.a | c++filt3
libstdc++.a(bitset.o):
00000000 A _ZNKSt12_Base_bitsetILm1EE15_M_do_find_nextEmm.eh # presumably these are just "private" symbols
00000000 A _ZNKSt12_Base_bitsetILm1EE16_M_do_find_firstEm.eh
0000005c T std::_Base_bitset<1ul>::_M_do_find_next(unsigned long, unsigned long) # now this looks useful!
const
-bob
_______________________________________________ Pythonmac-SIG maillist - Pythonmac-SIG@python.org http://mail.python.org/mailman/listinfo/pythonmac-sig