Opaque Objects / Pointers

In the context of ‘improving’ API usability, what do people think of them?

Having spent about 24 hours thinking about them, I can see many benefits
and only a few drawbacks, drawbacks that aren’t really drawbacks, they
are just shifting of responsibilities from one place to another.

Eddy

P.S. Yes, I have deliberately not described what an ‘opaque object’ is.

In the context of ‘improving’ API usability, what do people think of
them?

Depends… (On the situation, and on what we’re actually talking
about.) They can be handy in some situations, but I rarely feel a
real need for them.

Having spent about 24 hours thinking about them, I can see many
benefits and only a few drawbacks, drawbacks that aren’t really
drawbacks, they are just shifting of responsibilities from one place
to another.

Shifting responsibilities in that direction tends to also mean
shifting them away from the compiler to run-time type checking - that
is, slower code… Next, we run into a whole new set of issues with
typos, accidentally sending the wrong object to the wrong place etc;
stuff that an experienced C programmer expects the compiler to trap
right away.

It’s a different way of thinking, and, although I use it extensively
in my EEL scripting language (sort of like Lua with more C-like
syntax and slightly different design goals), I’m not sure it belongs
in a C API - or in an API at all, for that matter.

That said, what are these benefits you’re seeing?

Either way, I’m not sure what you’re talking about, so I might be
missing the point altogether. :wink:

//David Olofson - Programmer, Composer, Open Source Advocate

.------- http://olofson.net - Games, SDL examples -------.
| http://zeespace.net - 2.5D rendering engine |
| http://audiality.org - Music/audio engine |
| http://eel.olofson.net - Real time scripting |
’-- http://www.reologica.se - Rheology instrumentation --'On Friday 18 July 2008, Eddy Cullen wrote:

David Olofson wrote:

Either way, I’m not sure what you’re talking about, so I might be
missing the point altogether. :wink:

I want to try to get an idea of what people understand the concept to
mean, hence the deliberate vagueness; I don’t want to pollute other’s
opinions by expressing my own too clearly. (Plus, we all like playing
games, so why not play them on the list too? cheeky grin )

Shifting responsibilities in that direction tends to also mean
shifting them away from the compiler to run-time type checking - that
is, slower code… Next, we run into a whole new set of issues with
typos, accidentally sending the wrong object to the wrong place etc;
stuff that an experienced C programmer expects the compiler to trap
right away.

Interestingly, by ‘shifting responsibilities’, I meant from the user to
the library developer, not compiler to run-time.

That said, what are these benefits you’re seeing?

When dealing with ‘complex’ structures, that is a structure requiring a
deep copy (one for which a = b is semantically incorrect).

A good example of where an opaque object might be better is SDL_Surface.
Generally, SDL_Surface * is used everywhere, copying is a standard
process, so why not have a function to do it?

The drawbacks relate to maintaining binary compatibility, but they’re
actually not real; they are shifting the responsibility from one part of
the design process to another…

I’m not sure it belongs in a C API - or in an API at all, for that
matter.

I have been led to believe that information hiding is a Good Thing. The
issue, in my view, is that C lacks explicit support for it. Can this be
worked-around in a way that users find easy to understand, use, etc?

What are peoples experiences with it?

Eddy

[…]

Shifting responsibilities in that direction tends to also mean
shifting them away from the compiler to run-time type checking -
that is, slower code… Next, we run into a whole new set of
issues with typos, accidentally sending the wrong object to the
wrong place etc; stuff that an experienced C programmer expects
the compiler to trap right away.

Interestingly, by ‘shifting responsibilities’, I meant from the user
to the library developer, not compiler to run-time.

That may or may not be the same thing; they’re more or less
orthogonal…

[…]

That said, what are these benefits you’re seeing?

When dealing with ‘complex’ structures, that is a structure
requiring a deep copy (one for which a = b is semantically
incorrect).

Nothing requires a deep copy. It’s an expensive operation that you
only want done when you really need it - and that is, in most SDL
applications, never. :slight_smile:

Besides, “a = b” is not semantically incorrect in any way; it just
means “copy the pointer value held in ‘b’ into ‘a’”. :wink:

Personally, I dislike APIs that try to wrap things like this. C++ APIs
that “abuse” operator overloading to do this are even worse. It can
be “handy” and (in the case of C++) make the code look cleaner, but
for the most part, it just means you have to double check everything
all the time to be sure what’s actually going on.

I’m not sure it belongs in a C API - or in an API at all, for that
matter.

I have been led to believe that information hiding is a Good Thing.

It is, generally, but I don’t see how trying to hide fundamental
language constructs like pointers can ever be a Good Thing. The
correct solution to that problem is using a higher level language
that avoids these constructs entirely.

Now, I’m not saying deep copy of an SDL_Surface would be useless
(though I can’t remember ever needing it), but that’s just a matter
of adding a call SDL_CloneSurface() or something. IMNSHO, it’s a rare
special case, that does not, in any way, motivate any overall API
design changes.

The issue, in my view, is that C lacks explicit support for it. Can
this be worked-around in a way that users find easy to understand,
use, etc?

Well, you can make all structs “private” and provide function calls to
access the information instead, but all you gain from that is some
minor extra freedom in changing SDL internals without breaking source
and/or binary compatibility with applications, at the cost of
potentially significant overhead.

What are peoples experiences with it?

My experience is that overdoing this just leads to overcomplicated,
inefficient APIs for no real gain whatsoever.

IMHO, the SDL API is a brilliant example of how to do it right. It’s
lean and mean, easy to learn, efficient, and still allows backends
enough slack to do some pretty odd things. (Think glSDL…)

//David Olofson - Programmer, Composer, Open Source Advocate

.------- http://olofson.net - Games, SDL examples -------.
| http://zeespace.net - 2.5D rendering engine |
| http://audiality.org - Music/audio engine |
| http://eel.olofson.net - Real time scripting |
’-- http://www.reologica.se - Rheology instrumentation --'On Saturday 19 July 2008, Eddy Cullen wrote:

David Olofson wrote:

[…]

Shifting responsibilities in that direction tends to also mean
shifting them away from the compiler to run-time type checking -
that is, slower code… Next, we run into a whole new set of
issues with typos, accidentally sending the wrong object to the
wrong place etc; stuff that an experienced C programmer expects
the compiler to trap right away.

Interestingly, by ‘shifting responsibilities’, I meant from the user
to the library developer, not compiler to run-time.

That may or may not be the same thing; they’re more or less
orthogonal…

I really don’t know what you mean here - if they’re more-or-less
orthogonal, how can they be the same thing?

That said, what are these benefits you’re seeing?

When dealing with ‘complex’ structures, that is a structure
requiring a deep copy (one for which a = b is semantically
incorrect).

Nothing requires a deep copy. It’s an expensive operation that you
only want done when you really need it - and that is, in most SDL
applications, never. :slight_smile:

Besides, “a = b” is not semantically incorrect in any way; it just
means “copy the pointer value held in ‘b’ into ‘a’”. :wink:

LOL, okay Mr Smarty-Pants, just for you, I’ll be explicit.

When I said ‘a structure requiring a deep copy…’, I meant:

‘where obtaining a separate, independent copy of a structure and its
data requires a deep copy to be performed (where a = b is not
sufficient; where a = b is semantically incorrect).’

But I thought that was pretty obvious… :wink:

Seriously though…

Personally, I dislike APIs that try to wrap things like this. C++ APIs
that “abuse” operator overloading to do this are even worse. It can
be “handy” and (in the case of C++) make the code look cleaner, but
for the most part, it just means you have to double check everything
all the time to be sure what’s actually going on.

Is that really the case? The reason I chose SDL_Surface as an example,
is that it’s not immediately obvious how to clone it just by looking at
a list of functions (okay, could be ‘fixed’ by documentation, but surely
that is the definition of ‘less intuitive’). Also, the documentation states:

 /* This structure also contains private fields not shown here */

So it is at least semi-opaque already. Why not define the API to include
functions for querying the (almost exclusively) read-only data?

Granted, it may not be quite as nice to write:

SDL_Surface_width(surface);                          (1)

as it is:

surface->w;                                          (2)

But it would prevent a user from doing:

surface->w = 100; /* Semantically incorrect */

And it does, at least to me, seem 100% more obvious what surface refers
to in (1) when compared to (2). Again, the majority of overhead of
development is in maintenance, so the pain of typing a really verbose
statement, like (1) is surely off-set by the saving you’ll get when the
code is re-visited?

I have been led to believe that information hiding is a Good Thing.

It is, generally, but I don’t see how trying to hide fundamental
language constructs like pointers can ever be a Good Thing. The
correct solution to that problem is using a higher level language
that avoids these constructs entirely.

Well, given that pointer abuse remains one of the most common causes of
errors (OMFG, you should see some of the code I have to maintain at
work!), and that almost every language since C has tried to do exactly
that (even C++), I can’t see how ‘hiding pointers’ can be called a Bad
Thing. That is to say, if you don’t need to expose a pointer, what’s
the point (pun intended) of putting power and temptation into the hands
of a user?

Or lets look at it another way… SDL isn’t used ‘just’ in C programs -
it has bindings for many other languages, some of which don’t even HAVE
the concept of a pointer.

Now, I’m not saying deep copy of an SDL_Surface would be useless
(though I can’t remember ever needing it), but that’s just a matter
of adding a call SDL_CloneSurface() or something. IMNSHO, it’s a rare
special case, that does not, in any way, motivate any overall API
design changes.

But what if you DO need to do it? Granted, one can clone a surface using:

 new_surface = SDL_CreateRGBSurface(old_surface->flags,
     old_surface->w, old_surface->h,
     old_surface->format->BitsPerPixel,
     old_surface->format->Rmask,
     old_surface->format->Gmask,
     old_surface->format->Bmask,
     old_surface->format->Amask
 );
 SDL_BlitSurface(new_surface, NULL, old_surface, NULL);

But that seems a little obtuse to me.

 new_surface = SDL_CloneRGBSurface(old_surface);

Would do the same job, except neater. It would also prevent people
trying to copy the structure manually, as shown in the documentation.

The issue, in my view, is that C lacks explicit support for it. Can
this be worked-around in a way that users find easy to understand,
use, etc?

Well, you can make all structs “private” and provide function calls to
access the information instead, but all you gain from that is some
minor extra freedom in changing SDL internals without breaking source
and/or binary compatibility with applications, at the cost of
potentially significant overhead.

Yes, that’s the problem isn’t it… this is basically the problem
Stroustrup had when he first started to develop C++; people started to
circumvent the protection mechanism in order to avoid the overhead of a
function call, just to get at a member value, such as an int.

Surely, the goal of a library provider, is to do exactly that; provide
an interface that is stable, that a user can work to with certainty,
while allowing the library developer as much freedom as possible to
change the implementation details?

Incidentally, I’m not talking about all structs, for example, SDL_Rect
is simple (and small) enough to be perfectly understandable and safe
as it is, making it opaque would just be silly. SDL_Surface, on the
other hand, has up to 3 levels of indirection
(Surface->PixFormat->Palette->Color) and that’s just in the public part!

What are peoples experiences with it?

My experience is that overdoing this just leads to overcomplicated,
inefficient APIs for no real gain whatsoever.

IMHO, the SDL API is a brilliant example of how to do it right. It’s
lean and mean, easy to learn, efficient, and still allows backends
enough slack to do some pretty odd things. (Think glSDL…)

I’m not saying it doesn’t. I am asking if it is perfect and if it
isn’t, how can I help to improve it?

Eddy> On Saturday 19 July 2008, Eddy Cullen wrote:

A) Because it’s arrogant beyond belief for anyone to assume they know more
than every other programmer in existence.

B) Because power rightfully belongs in the hands of the developer (not user).
It is incumbent upon every professional developer to know his/her tools well
enough to not do stupid things. Creating tools that hobble the developer so
that undisciplined kids can “program” is one reason why so much software
today is crap. Not the only reason by any means, but a significant reason.

JeffOn Sat July 19 2008 13:44, Eddy Cullen wrote:

That is to say, if you don’t need to expose a pointer, what’s
the point (pun intended) of putting power and temptation into the hands
of a user?

Hello !

Theoretical it is better to hide information
from the user, like how for example the width
of a surface is implemented as an int or as a float.

But things like width of a surface and other small
infos tend to be asked a lot, so it really decreases the
performance of your app.

If you want to make SDL better, write a SDL helper lib
and add all the functions like SDL_CloneSurface, SDL_GetPixel,
SDL_SetPixel and every other function that is not needed in SDL
directly, but maybe nice to have to it.

CU

I consider this statement the end of it all : one can implement an
opaque concept on top of SDL as it is now, but not vice versa.

that’s why SDL is so good.

If you really need the black box so desperately, make wrapper and
force your team to use that one.> Hello !

Theoretical it is better to hide information
from the user, like how for example the width
of a surface is implemented as an int or as a float.

But things like width of a surface and other small
infos tend to be asked a lot, so it really decreases the
performance of your app.

If you want to make SDL better, write a SDL helper lib
and add all the functions like SDL_CloneSurface, SDL_GetPixel,
SDL_SetPixel and every other function that is not needed in SDL
directly, but maybe nice to have to it.

CU


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

Isn’t SDL_ConvertSurface pretty much what you’re asking for in the way of deep-copy? I agree with David that we can’t have SDL as a low-level library that forces programmers to work on a higher level. There is enough functionality that is missing from SDL for people to implement because SDL just lets you get access to stuff more easily. SDL cannot be everything to everyone, while still fulfilling its mission, so it has to open up its structs a little. If SDL were fully implemented in C++, the function and method overhead would be a little crazy, which makes all the gray-bearded and pint-size CPUs sad.

Jonny D

Hello !

Isn’t SDL_ConvertSurface pretty much what you’re asking for in the
way of deep-copy? I agree with David that we can’t have SDL as a

SDL_ConvertSurface and SDL_DisplayFormat change both either
the source or destination surface formats. SDL_CloneSurface
would be a function that creates another surface with the
exact same parameters and exact same pixeldata as the source
SDL_Surface.

CU

SDL_ConvertSurface and SDL_DisplayFormat change both either
the source or destination surface formats. SDL_CloneSurface
would be a function that creates another surface with the
exact same parameters and exact same pixeldata as the source
SDL_Surface.

I’ve posted this before and nobody corrected me:
static inline SDL_Surface* SPG_CopySurface(SDL_Surface* src)
{
return SDL_ConvertSurface(src, src->format, SDL_SWSURFACE);
}

The only thing it doesn’t do is copy over the colorkey, surface alpha, etc.
Doesn’t this do what is needed?

Jonny D

Hello !

I’ve posted this before and nobody corrected me:
static inline SDL_Surface* SPG_CopySurface(SDL_Surface* src)
{
return SDL_ConvertSurface(src, src->format, SDL_SWSURFACE);
}

The only thing it doesn’t do is copy over the colorkey, surface alpha, etc.
Doesn’t this do what is needed?

SDL_CloneSurface would copy all the data from the original surface,
pixel data, surface alpha, color key, hw surface or not …

CU

[…]

Interestingly, by ‘shifting responsibilities’, I meant from the
user to the library developer, not compiler to run-time.

That may or may not be the same thing; they’re more or less
orthogonal…

I really don’t know what you mean here - if they’re more-or-less
orthogonal, how can they be the same thing?

Sorry, what I meant was that when it comes to implementation, one may
bring the other, though the concepts are theoretically orthogonal.

For example, you can shift the responsibility of chosing the
correct “destructor” into a library by having a generic Destroy()
function that takes a void * or similar argument - but that means you
have to use some kind of object model that allows the Destroy()
implementation to figure out who to call to get the job done.

[…]

When I said ‘a structure requiring a deep copy…’, I meant:

‘where obtaining a separate, independent copy of a structure and its
data requires a deep copy to be performed (where a = b is not
sufficient; where a = b is semantically incorrect).’

Well, that’s actually a pretty hard problem in real applications. How
deep is a deep copy…? Maybe you need refcounting and copy-on-write
for performance reasons, or maybe that would just be a waste of
cycles?

This is something that has to be decided on the
application/engine/higher level library level, and I think building
that sort of stuff into a low level API like SDL would only confuse
matters and make it harder to use properly.

Basically, when it’s not clear what the correct way of doing something
is, it’s better to leave the decision to the application code.

[…]

Personally, I dislike APIs that try to wrap things like this. C++
APIs that “abuse” operator overloading to do this are even worse.
It can be “handy” and (in the case of C++) make the code look
cleaner, but for the most part, it just means you have to double
check everything all the time to be sure what’s actually going on.

Is that really the case? The reason I chose SDL_Surface as an
example, is that it’s not immediately obvious how to clone it just
by looking at a list of functions (okay, could be ‘fixed’ by
documentation, but surely that is the definition of ‘less
intuitive’).

Well, if you step back and look at the problem: When do you want to
clone an SDL_Surface? If you ever want to do it, why?

It turns out that it’s pretty much a non-issue, because the few times
you actually do want a copy, you actually want a slightly different
version, such as a version suitable for fast blitting to the screen
(SDL_DisplayFormat*()), or a temporary version in some specific,
handy format for some direct pixel level manipulation.

Also, the documentation states:

 /* This structure also contains private fields not shown here 

*/

So it is at least semi-opaque already. Why not define the API to
include functions for querying the (almost exclusively) read-only
data?

Because it’s just more typing, and doesn’t really prevent anything but
silly typos…?

If the documentation states that these fields are read-only, that
pretty much covers it, IMHO.

Granted, it may not be quite as nice to write:

SDL_Surface_width(surface); (1)

as it is:

surface->w; (2)

But it would prevent a user from doing:

surface->w = 100; /* Semantically incorrect */

Maybe I’m a superhuman coder or something, but I don’t think I’ve ever
made that particular mistake, actually. :slight_smile:

And it does, at least to me, seem 100% more obvious what surface
refers to in (1) when compared to (2). Again, the majority of
overhead of development is in maintenance, so the pain of typing a
really verbose statement, like (1) is surely off-set by the saving
you’ll get when the code is re-visited?

You’re forgetting that SDL is a pretty low level API, that is
sometimes getting dangerously close to the dreaded “inner loops” of
performance critical software. Turning raw field accesses into
function calls - or even inlines that can potentially confuse the
optimizer - needs to be strongly motivated.

If you want it all nice and fool-proof, C is not for you, and nor is
the raw SDL API. There are various real high level language bindings
for SDL (including work-in-progress EEL/EELBox) that do a much better
job of this than C or C++ ever could. They’re not as fast as C or
C++, but the difference tends to be irrelevant, unless you’re working
on handheld devices and/or doing rather low level work. Even when you
do need the best raw performance you can get, these tools can save
a great deal of time by allowing you to prototype and get the
algorithms right before you start hacking C code.

[…]

I have been led to believe that information hiding is a Good
Thing.

It is, generally, but I don’t see how trying to hide fundamental
language constructs like pointers can ever be a Good Thing. The
correct solution to that problem is using a higher level language
that avoids these constructs entirely.

Well, given that pointer abuse remains one of the most common causes
of errors (OMFG, you should see some of the code I have to maintain
at work!), and that almost every language since C has tried to do
exactly that (even C++), I can’t see how ‘hiding pointers’ can be
called a Bad Thing. That is to say, if you don’t need to expose a
pointer, what’s the point (pun intended) of putting power and
temptation into the hands of a user?

How do you actually hide pointers when dealing with a C API in C? :wink:

(Yeah, I know it’s possible, and I’ve even tried it in some of my
older APIs - but it tends to cause more problems than it solves.)

IMHO, the correct answer is: Pick a nice high level language without
pointers, and make a binding for it.

Or lets look at it another way… SDL isn’t used ‘just’ in C
programs - it has bindings for many other languages, some of which
don’t even HAVE the concept of a pointer.

Exactly. :wink:

[…cloning a surface…]

But what if you DO need to do it? Granted, one can clone a surface
using:

 new_surface = SDL_CreateRGBSurface(old_surface->flags,
     old_surface->w, old_surface->h,
     old_surface->format->BitsPerPixel,
     old_surface->format->Rmask,
     old_surface->format->Gmask,
     old_surface->format->Bmask,
     old_surface->format->Amask
 );
 SDL_BlitSurface(new_surface, NULL, old_surface, NULL);

But that seems a little obtuse to me.

Actually, I’m not even sure if that handles every surface correctly -
so yes, you have a point there.

 new_surface = SDL_CloneRGBSurface(old_surface);

Would do the same job, except neater. It would also prevent people
trying to copy the structure manually, as shown in the
documentation.

So, an add-on library with handy tools like that would be a nice thing
to have… :slight_smile:

[…]

The issue, in my view, is that C lacks explicit support for it.
Can this be worked-around in a way that users find easy to
understand, use, etc?

Well, you can make all structs “private” and provide function
calls to access the information instead, but all you gain from
that is some minor extra freedom in changing SDL internals without
breaking source and/or binary compatibility with applications, at
the cost of potentially significant overhead.

Yes, that’s the problem isn’t it… this is basically the problem
Stroustrup had when he first started to develop C++; people started
to circumvent the protection mechanism in order to avoid the
overhead of a function call, just to get at a member value, such as
an int.

It’s a problem C was never designed to solve, so it’s kind of hard to
solve it in C without adding overhead or making things cumbersome…
I just don’t think it’s worth the effort. :slight_smile:

Surely, the goal of a library provider, is to do exactly that;
provide an interface that is stable, that a user can work to with
certainty, while allowing the library developer as much freedom as
possible to change the implementation details?

Sure, but how far can we afford to take it? There’s no such thing as a
free lunch.

Much of the point with SDL is exactly to allow low level access to
things, and doing that while at the same time being open to arbitrary
pixel formats, weird backends and whatnot requires an incredibly
complex API - or one that’s simple but generates lots of data
conversion overhead.

I mean, you could just hide all the raw pixel data details and provide
SDL_SetPixel() and SDL_GetPixel() calls with 32 bits per channel, and
cover pretty much everything. However, any applications doing pixel
level software rendering would invariably be dog slow, unless they
could bypass that - and if they could, we’d be back at square one
again, exposing “internals” in the API.

SDL strikes a pretty good balance here. It supports most pixel formats
of interest, it supports most kinds of backends (software and
accelerated) pretty well, and it provides a reasonably clean and
simple API that allows enough low level access for most things you
ever want to do in a portable multimedia application.

[…]

Incidentally, I’m not talking about all structs, for example,
SDL_Rect is simple (and small) enough to be perfectly understandable
and safe as it is, making it opaque would just be silly.
SDL_Surface, on the other hand, has up to 3 levels of indirection
(Surface->PixFormat->Palette->Color) and that’s just in the public
part!

You need that information exposed anyway, to be able to do pixel level
access from application code. Maybe you never need that, and maybe
SDL just isn’t the right tool for the jobs you do?

[…]

What are peoples experiences with it?

My experience is that overdoing this just leads to
overcomplicated, inefficient APIs for no real gain whatsoever.

IMHO, the SDL API is a brilliant example of how to do it right.
It’s lean and mean, easy to learn, efficient, and still allows
backends enough slack to do some pretty odd things. (Think
glSDL…)

I’m not saying it doesn’t. I am asking if it is perfect and if
it isn’t, how can I help to improve it?

Well, nothing is perfect, but that’s life. :slight_smile:

There are various issues that people are complaining about from time
to time, but I think most of these have been dealt with in SDL 1.3
already. Unfortunately, I’ve been out of the loop for too long to say
anything about the details at this point.

//David Olofson - Programmer, Composer, Open Source Advocate

.------- http://olofson.net - Games, SDL examples -------.
| http://zeespace.net - 2.5D rendering engine |
| http://audiality.org - Music/audio engine |
| http://eel.olofson.net - Real time scripting |
’-- http://www.reologica.se - Rheology instrumentation --'On Saturday 19 July 2008, Eddy Cullen wrote:

Also, the documentation states:

/* This structure also contains private fields not shown here */

So it is at least semi-opaque already. Why not define the API to include
functions for querying the (almost exclusively) read-only data?

Granted, it may not be quite as nice to write:

SDL_Surface_width(surface); (1)

as it is:

surface->w; (2)

But it would prevent a user from doing:

surface->w = 100; /* Semantically incorrect */

I’m trying not to laugh hysterically here. A bunch of people have replied to this saying that the extra function calls for this, (C++ style,) would necessarily either add more overhead or introduce confusing inlines. It’s discussions like this that make me so glad I use Delphi. They discovered the ideal solution to this problem years and years ago, and for whatever reason, the C family has never caught on.

In Delphi, you can define a record (struct) or a class with hidden private members (a good thing, as everyone seems to more or less agree,) and then represent the interface to them with transparent “properties” that look like variables to the coder. A property can be set as read-only, write-only (which may sound strange but is occasionally useful,) or read-write. The read and write sub-properties can be declared either as functions or as private variables. It’s common to see something declared with its read property set as the variable itself (which the compiler simply substitutes automagically, no inlining required) and its write property set as a function which sets up the new value and resolves any other related data updates.

The ideal solution here, then, would be to delcare surface->h and surface->w as read-only properties that directly access the internal variables. If the compiler sees a read attempt, it substitutes the variable. If it sees a write attempt, it gives a compiler error, (“cannot assign to a read-only property”), which is always better than whatever undefined behavior would result from such an assignment taking place at runtime.

This is such an obvious improvement, and Borland’s been doing it for over a decade. Anyone know why C/C++ has never caught on?

----- Original Message -----
From: eac203@ecs.soton.ac.uk (Edward Cullen)
Subject: Re: [SDL] Opaque Objects / Pointers

Hello !

In Delphi, you can define a record (struct) or a class with hidden
private members (a good thing, as everyone seems to more or less
agree,) and then represent the interface to them with transparent
"properties" that look like variables to the coder. A property can
be set as read-only, write-only (which may sound strange but is
occasionally useful,) or read-write. The read and write
sub-properties can be declared either as functions or as private
variables. It’s common to see something declared with its read
property set as the variable itself (which the compiler simply
substitutes automagically, no inlining required) and its write
property set as a function which sets up the new value and resolves
any other related data updates.

The ideal solution here, then, would be to delcare surface->h and
surface->w as read-only properties that directly access the internal
variables. If the compiler sees a read attempt, it substitutes the
variable. If it sees a write attempt, it gives a compiler error,
(“cannot assign to a read-only property”), which is always better
than whatever undefined behavior would result from such an
assignment taking place at runtime.

This is such an obvious improvement, and Borland’s been doing it for
over a decade. Anyone know why C/C++ has never caught on?

The biggest problem is when speed matters. For high level things that
are only called a few times per second, this is usefull, no question.

But what about for example the linux kernel and other low level software
apps. You would never want them to use such things. When you access
things like bytes, ints 10000 times a second or 100000 times you would
want them to be as fast as possible.

CU

Hello !

The biggest problem is when speed matters. For high level things that
are only called a few times per second, this is usefull, no question.

But what about for example the linux kernel and other low level software
apps. You would never want them to use such things. When you access
things like bytes, ints 10000 times a second or 100000 times you would
want them to be as fast as possible.
I don’t see how that’s a problem. Just use properties that reference the variable directly, and it’s no slower at runtime than using the struct->member notation; the compiler just substitutes the one for the other automagically. The advantages are in flexibility, (I remember one time, when I needed to have a value change over time, I set up one property that read from one variable but wrote to a different one, completely transparently,) and in error prevention; the compiler will catch a lot of potential bugs instead of letting them make it into your software.>----- Original Message ----
From: Torsten Giebl
Subject: Re: [SDL] Opaque Objects / Pointers

[…Delphi properties…]

This is such an obvious improvement, and Borland’s been doing it for
over a decade. Anyone know why C/C++ has never caught on?

Yeah, I’m well aware of that feature, having written a few
applications in Delphi. I think it’s about as annoying as it is
handy, at least when it’s “abused” to trigger heavy GUI updates in
VCL/CLX. :slight_smile:

In the case of C, one reason might be that it basically doesn’t fit
into a language without explicit OO. Sure, you could just stop at
declaring fields as read-only or write-only, but there’s still a
problem: How do you say what code is allowed to “violate” this, to
actually make use of the fields? (C structs don’t have member
functions…)

When it comes to C++, well, that’s more of a language toolkit than an
actual language, and I think you could actually implement it using
existing features. I’m not exactly a C++ master (I don’t even like
C++ very much), but it seems to me that declaring special types with
overloaded operators would do the trick… (The declarations would be
a bit messy, as operator overloading deals with the actual objects
involved, rather than whatever “containers” they may be in.)

Either way, I prefer it when you know what the ‘=’ operator does, and
so I actually prefer the standard C++ approach with "setter/getter"
functions, if anything like that is to be used at all.

//David Olofson - Programmer, Composer, Open Source Advocate

.------- http://olofson.net - Games, SDL examples -------.
| http://zeespace.net - 2.5D rendering engine |
| http://audiality.org - Music/audio engine |
| http://eel.olofson.net - Real time scripting |
’-- http://www.reologica.se - Rheology instrumentation --'On Sunday 20 July 2008, Mason Wheeler wrote:

Torsten Giebl wrote:

Hello !

In Delphi, you can define a record (struct) or a class with hidden
private members (a good thing, as everyone seems to more or less
agree,) and then represent the interface to them with transparent
"properties" that look like variables to the coder. A property can be
set as read-only, write-only (which may sound strange but is
occasionally useful,) or read-write. The read and write
sub-properties can be declared either as functions or as private
variables. It’s common to see something declared with its read
property set as the variable itself (which the compiler simply
substitutes automagically, no inlining required) and its write
property set as a function which sets up the new value and resolves
any other related data updates.

The ideal solution here, then, would be to delcare surface->h and
surface->w as read-only properties that directly access the internal
variables. If the compiler sees a read attempt, it substitutes the
variable. If it sees a write attempt, it gives a compiler error,
(“cannot assign to a read-only property”), which is always better
than whatever undefined behavior would result from such an assignment
taking place at runtime.

This is such an obvious improvement, and Borland’s been doing it for
over a decade. Anyone know why C/C++ has never caught on?

The biggest problem is when speed matters. For high level things that
are only called a few times per second, this is usefull, no question.

But what about for example the linux kernel and other low level software
apps. You would never want them to use such things. When you access
things like bytes, ints 10000 times a second or 100000 times you would
want them to be as fast as possible.

This is a rather hollow claim. Speed tests have shown that Object Pascal
beats other compiled languages. But that’s another hollow claim since
any speed differential is compiler and application specific and requires
actual testing, I’m sure that Delphi has nothing to be ashamed of in
this arena (except perhaps portability). If speed is the bottom line,
the least portable language of all comes to the rescue, machine language.

That said, it’s not properties that have failed to catch on, it’s
Pascal. It’s used in some areas, but C and variants have dominated the
market, there are other languages that gain footholds here and there,
but C and C++ aren’t going away any too soon.

It’s easy to argue the best cure for a theoretical problem, but where
there’s a real problem, answers are not difficult.

CWC

Hello !

That said, it’s not properties that have failed to catch on, it’s
Pascal. It’s used in some areas, but C and variants have dominated the
market, there are other languages that gain footholds here and there,
but C and C++ aren’t going away any too soon.

After learning BASIC, i learned PASCAL and then C.
It sounds dumb, but one reason why C won over PASCAL
is just because you have to type less.
{ for begin, …

And pointer look a little bit nicer in C than they do in Pascal.

CU

This is such an obvious improvement, and Borland’s been doing it for over a decade. Anyone know why C/C++ has never caught on?
-Mason

It’s used in some areas, but C and variants have dominated the
market, there are other languages that gain footholds here and there,
but C and C++ aren’t going away any too soon.
-CWC

“So, Lone Starr, now you see that evil will always triumph because good is dumb.”
-Dark Helmet