[Pythonmac-SIG] Re: Mac newbie

Bob Ippolito bob at redivi.com
Mon Feb 14 21:46:30 CET 2005


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



More information about the Pythonmac-SIG mailing list