Opaque Objects / Pointers

By user, I meant someone who uses the library, i.e. a developer using
the library.

Jeff wrote:> On 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?

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.

Jeff


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

So, like, a macro that uses memcpy() and sizeof(SDL_Surface)? ;)On Sat, Jul 19, 2008 at 10:14:35PM +0000, Torsten Giebl wrote:

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.


-bill!
“Tux Paint” - free children’s drawing software for Windows / Mac OS X / Linux!
Download it today! http://www.tuxpaint.org/

Hello !

So, like, a macro that uses memcpy() and sizeof(SDL_Surface)? :wink:

But you would have to check for HW Surfaces, too.

CU

sigh

He was being sarcastic, Torsten.

Eddy

Torsten Giebl wrote:> Hello !

So, like, a macro that uses memcpy() and sizeof(SDL_Surface)? :wink:

But you would have to check for HW Surfaces, too.

CU


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

Hello !

sigh

He was being sarcastic, Torsten.

Shame on me.

CU

First and foremost, I *sick* to death of reading "if you don't like it, use something else" like I'm some kind of a f***tard or whiney s'kiddy.

I’m not. I’m a serious developer, attempting to explore an important
subject in an intelligent way. I’m fed-up of reading:

  • It’s alright for me.
  • If you don’t like it, use something else.
  • Maybe C isn’t the language for you.
  • That’s not the way things are done at the moment (so we’re not going
    to do them that way in the future.)
  • Write an add-on library to…

Understand the context:

The SDL API IS CHANGING. It will likely continue to change. This is
tacit acknowledgement that “the current way” isn’t quite right.

If you remember, the topic of this thread is “Opaque Objects /
Pointers”. Implicitly, you can add “should they be used in SDL?”.

As for the C language… OMG! I WISH I didn’t know C so well, because it
wouldn’t PISS ME OFF AS MUCH WHEN PEOPLE INSINUATE THAT I DON’T KNOW
WHAT I’M TALKING ABOUT!

STOP taking swipes at me and answer the sodding question!

Now that I’ve got that off my chest:

David Olofson wrote:

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.

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.

Right, get you now.

What one could do is specify a large structure that the user may want
many copies of, say a generic structure for holding pixel data.

Now, this structure could be so large that no developer would ever in
practice
pass it by value.

So, as a library developer, what do you do? You COULD make the developer
do this:

PixelStruct ps;
InitPixelStruct(&ps, arg1, arg2, arg3);

or
PixelStruct *ps = malloc(sizeof(PixelStruct));
InitPixelStruct(ps, arg1, arg2, arg3);

Or, alternatively, you could just acknowledge the fact in your API and
give them something simple and easy to use, like this:

PixelStruct *ps = NewPixelStruct(arg1, arg2, arg3);

Now you can argue until the cows come home about HOW NewPixelStruct is
implemented (whether malloc’ed or a static array or some other
memory-pooling scheme), but most of the time, the user won’t really be
bothered, because, at the end of the day, there’s a VERY good chance
that they’d just do it the way you would. And if they need a really
specific scheme, then they’ll either:

 1. Just write it themselves

or
2. Ask you to write a similar function that implements a different
scheme.
or
3. Use something else

My point, is that by using a 3rd party library in the first place,
you’re prepared to sacrifice some level of control over the
implementation details, for the time, effort & COST savings that you
get by not having to write it all yourself.

Now the purpose of this example is to make this point: If you’re going
to provide a library function and you’re NOT prepared to say “This is
how we’ve decided to implement this”, then you may as well give up and
go home.

Of course, what you could do is implement a function one way, get
feedback from your customers and if they don’t like it, or lets say, you
come up with a more efficient method on your own, then you can always
replace the implementation and it will be transparent to your customers
(because you’ve not changed the API…).

But then, of course, unless they’ve profiled their code and highlighted
that library function as a particular bottle-neck, then they probably
won’t even care.

When was the last time you really cared about the implementation of
say, printf() on a desktop system? You don’t. All you care about is that
it’s there and it works.

As a user of an API that ALL you generally care about; does it do the
job I want? Is it easy to use? The rest, you trust the developer to make
sensible choices on your behalf. Of course, if they’ve released the
source to you, say, under LGPL, then you can always check it, to satisfy
yourself.

[…]

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.

So, if it’s a rare thing, you’re not really gonna be fussed if it
isn’t particularly ‘quick’ are you? But when you DO need it, you’re
probably gonna be pissed that it’s not there at all.

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.

Okay, but my experience is that if you give someone opportunity to do it
wrong, then they will. Hell, I’ve seen someone copy a string constant
error message into a temporary buffer using strcpy() before displaying it.

Yes, you can NEVER legislate for people who really don’t know what
they’re doing, but you CAN make it harder for them to do something
stupid (which you’ll get blamed for, of course!)

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.

But what about using function-style macros?

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.)

How so?

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:

Again, goes back to the library trade-off and the shifting
responsibilities thing; if 99% users of your library are going to do
something you didn’t do because of ‘efficiency’ concerns, then you’re
not actually saving anything.

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?

Then if you had a opaque struct, you’d have an API for exposing that
data! The point about the levels of indirection was in regard to
deep-copying.

An opaque struct doesn’t mean you can’t access the data you need, it
means you can’t access it using the a->member syntax.

Eddy

You’re missing the point of my question entirely. It’s not a question of
the capabilities of SDL, it is about how the are expressed to the user.
Can the APIs be presented in a different way that is more user-friendly?

If SDL were fully implemented in C++ it probably wouldn’t be that much
bigger, because the developers stick to a sub-set of C++ that had the
lowest overhead and would take advantage of things like inlining and
templates that would actually reduce the size of the run-time code (yeah
the lib might be bigger).

C++ only really grows over C when you start to use things like
exceptions; the run-time and size overhead of using inheritance isn’t
actually that big (1 or 2 extra level of pointer indirection), unless
you go crazy, that is…

Jonathan Dearborn wrote:> 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



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

Read this article:

http://www.acmqueue.com/modules.php?name=Content&pa=showpage&pid=488

Find the comment on page 3 about layering of abstraction.

Eddy

jeroen clarysse wrote:> 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


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

I’m (normally) a C++ programmer, and while I can see that there are
advantages to using an opaque struct, the disadvantages far outweigh
them.

Let’s look at surfaces first, as they seem to be the focus of this
discussion. For a surface, regardless of whether it’s hardware,
software, on Windows, Linux, Mac or whatever, there are a bunch of
state variables which are common between them.

SDL is mature enough now that we (and users) can be fairly sure that
they’re not going to change or be reordered in the struct, breaking
binary compatibility.

I think platform specific surface data is already hidden.

Additionally, having visible access to these makes SDL simpler in
usage and implementation, and much more debuggable. Try putting a
breakpoint in code and inspecting a surface’s width or flags when it’s
all hidden behind some opaque pointer. Sure, it’s possible, but it’s
an extra hassle that I could do without.

Regarding surface copying, I usually use SDL_ConvertSurface and pass
the original surface’s format. I’m fairly sure it keeps the colour key
and alpha information but I’d need to check.

To be honest, I hardly ever need to do a deep surface copy. I share
surfaces using "boost intrusive_ptr"s.

Peter

Peter Mackay wrote:

Additionally, having visible access to these makes SDL simpler in
usage and implementation, and much more debuggable. Try putting a
breakpoint in code and inspecting a surface’s width or flags when it’s
all hidden behind some opaque pointer. Sure, it’s possible, but it’s
an extra hassle that I could do without.

Okay, that’s a fair point, however, I’m not so sure how valid it is
(anymore) - GDB has support for macros, so inspecting values is straight
forward.

I have no idea what macro support like in IDEs like MSVC & Xcode (most
’free’ alternatives use GDB).

Hello !

Lets talk it from the practical direction :

  1. What language do you choose ?
    It is possible to use the features of a language A in
    language B, but only to a certain level.

  2. How does the Video API part in your SDL look like ?
    For example write the new code of the SDL_Surface struct.
    What would it look like ? What about SDL_LoadBMP for example ?
    What is the new form of that ?

In the end it comes all to the API design.
The implementation can be hidden away from the enduser.
The API is what the enduser, better the developer is interested in.

CU

[…]

When was the last time you really cared about the implementation
of say, printf() on a desktop system? You don’t. All you care about
is that it’s there and it works.

Well, actually, it happends every now and then that I do care, because
the implementations cause real problems in some situations. That’s
not really relevant to this discussion, though…

As a user of an API that ALL you generally care about; does it do
the job I want? Is it easy to use? The rest, you trust the developer
to make sensible choices on your behalf.

Indeed, but what I’m talking about here is not whether the application
developer really cares about the actual details of the
implementation, but rather, what impact the API design has on the
performance of the implementation. I know all too well that lots of
developers couldn’t care less about performance, but that’s a luxury
many other developers don’t have.

What’s been discussed so far is nothing that would have any
significant performance impact, but in a large system or application,
these things tend to build up. One needs to keep an eye on that.

Of course, if they’ve released the source to you, say, under LGPL,
then you can always check it, to satisfy yourself.

That's why I use Open Source tools and software almost exclusively these days, both professionally and for my private projects. It might not be a big deal if you're an ordinary developer doing ordinary stuff (whatever that is...), but embeded systems, real time, systems that need maintenance for 10+ years etc; that's when the "mainstream" solutions start to cause problems.

So, I guess I’m a bit more paranoid than your average game developer
really needs to be. :wink:

[…]

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.

So, if it’s a rare thing, you’re not really gonna be fussed if it
isn’t particularly ‘quick’ are you? But when you DO need it, you’re
probably gonna be pissed that it’s not there at all.

Performance isn’t the issue here. Library size is.

Why isn’t this in the FAQ? (Or am I just blind?)

Q: Can you please add function SDL_Xyz() to SDL?
add-on library (ie doesn’t depend on SDL internals), it
most probably does not belong in the SDL core library.

Most of us really like the idea of keeping the SDL core library as
lean and mean as possible, without impairing it’s usability.

Personally, I sometimes think that it would be very handy with some
general SDL_tools library with all sorts of handy stuff. However, it
seems that SDL developers (like most developers) tend to roll their
own library of handy tools, or just keep a copy-paste library of
handy code.

Either there isn’t enough interest in creating and mantiaining an
SDL_tools library, or we can’t agree on how to do it, or both. So, it
doesn’t happen - and most of us are happy campers anyway. :slight_smile:

[…]

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

Okay, but my experience is that if you give someone opportunity to
do it wrong, then they will. Hell, I’ve seen someone copy a string
constant error message into a temporary buffer using strcpy() before
displaying it.

Yes, you can NEVER legislate for people who really don’t know what
they’re doing, but you CAN make it harder for them to do something
stupid (which you’ll get blamed for, of course!)

I see your point… One might claim that such people shouldn’t be
programming, but they are, and that’s just the way it is. I’m
spending a lot of my time as a “one man team”, so I only got myself
to blame for most of the stupidity I see, but I realize most
programmers have to face a different reality.

Now, OTOH, who is SDL for?

It might be advertised as “simple”, but you know; everything is
relative. It is indeed simple to me - but I started out coding
sound and graphics to the metal, in assembly language. :slight_smile:

I’m simply not sure it’s a good idea letting your average high level
application programmer anywhere near an SDL_Surface struct. They
should probably deal with higher level objects, and preferably,
higher level languages.

Personally, I don’t care much for safety measures that serve no other
purpose than preventing incompetent programmers from doing stupid
things. What can I say? I don’t see the point in doing extra typing
to avoid mistakes that I don’t do myself, even though I can see how
it can potentially serve some purpose in an “abuse” situation.

[…]

But what about using function-style macros?

Yeah, that, or (if we assume C99) even inline functions - but to me,
and apparently, quite a few others on this list, it’s just extra
typing for the application coder.

Besides, if it’s implemented like that, there’s no binary level
abstraction, so there goes (IMHO) the only real advantage. Sure, it’s
as fast as what we do now, but the only “bonus” is us doing some
extra typing, so… :wink:

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.)

How so?

Well, this is actually going one step further, so it’s not really
about opaque pointers.

Anyway, I’ve done a few APIs using opaque handles (internal table
indices and the like), and they’re kind of handy in small, simple
applications; you can do things like passing -1 for “all objects” and
stuff, and it’s trivial to deal with ranges of objects.

Beyond that however, they offer little more than making certain
mistakes easier to track. Actually, with proper debugging tools (like
Valgrind), this design makes applications harder to debug than
direct pointers, while offering nothing that these tools cannot do
anyway.

So… I can’t really think of any good reason to recommend this kind
of design for anything. It doesn’t really help C and the like, and a
high level language can usually offer much better solutions anyway.

[…]

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:

Again, goes back to the library trade-off and the shifting
responsibilities thing; if 99% users of your library are going to do
something you didn’t do because of ‘efficiency’ concerns, then
you’re not actually saving anything.
[…]

Well, let’s turn it around a bit: Who needs to access the information
at all? And, what level of “safety” is required for those who do
need access?

As most people won’t need to touch the fields of an SDL_Surface
anyway, why not replace the SDL_Surface pointers throughout
the “normal” API with an opaque pointer type. (Give them
SDL_SurfaceWidth() etc; only what’s really needed.)

Then offer a typecast macro that returns essentially a pointer to the
current SDL_Surface. The declarations for this could be in a separate
header that isn’t included in “normal” applications.

That way, us hardcore low level guys can have it our way, and you can
have your build scripts yell att untrusted programmers if they ever
try to use that typecast macro. :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 Sunday 20 July 2008, Eddy Cullen wrote:
A: If function SDL_Xyz() can be implemented in a separate

David Olofson wrote:

As a user of an API that ALL you generally care about; does it do
the job I want? Is it easy to use? The rest, you trust the developer
to make sensible choices on your behalf.

Indeed, but what I’m talking about here is not whether the application
developer really cares about the actual details of the
implementation, but rather, what impact the API design has on the
performance of the implementation. I know all too well that lots of
developers couldn’t care less about performance, but that’s a luxury
many other developers don’t have.

What’s been discussed so far is nothing that would have any
significant performance impact, but in a large system or application,
these things tend to build up. One needs to keep an eye on that.

Absolutely! That’s why I asked for peoples views on the use of opaque
objects. As an engineer, I deal in trade-offs; the trade-off here, is
(potential) performance cost against (potential) benefit to the
’majority’ of users (that is, in my experience ‘good’ programmers are in
the minority).

This is another important aspect of my motivation; ‘the majority’ are
(unfortunately) the the ones who get things done. So as the
minority, the most productive use of our time, is to try to make it
harder for the majority to do things badly. Yes, you may refer to me as
CynicalEddy.

[…]

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.
So, if it’s a rare thing, you’re not really gonna be fussed if it
isn’t particularly ‘quick’ are you? But when you DO need it, you’re
probably gonna be pissed that it’s not there at all.

Performance isn’t the issue here. Library size is.

Why isn’t this in the FAQ? (Or am I just blind?)

Q: Can you please add function SDL_Xyz() to SDL?
add-on library (ie doesn’t depend on SDL internals), it
most probably does not belong in the SDL core library.

Most of us really like the idea of keeping the SDL core library as
lean and mean as possible, without impairing it’s usability.

As do I. I fully appreciate the ‘thin’ nature of SDL. From what I
understand, keeping the API minimalistic is ‘good design’.

Personally, I sometimes think that it would be very handy with some
general SDL_tools library with all sorts of handy stuff. However, it
seems that SDL developers (like most developers) tend to roll their
own library of handy tools, or just keep a copy-paste library of
handy code.

Either there isn’t enough interest in creating and mantiaining an
SDL_tools library, or we can’t agree on how to do it, or both. So, it
doesn’t happen - and most of us are happy campers anyway. :slight_smile:

Yes. This goes back to the balance; how much is enough for the API to be
’complete’, without being over-burdened.

Actually, that’s a good question - is there a certain minimal API that
you should always have, even if some of the functions would be used
very rarely?

That is, if copying a particular structure is a valid operation, then,
perhaps, one should always provide a function to do it, even if it’s
only ever used in 1:10 programs?

One interesting, related, issue is symmetry in APIs (and in general).
Ever done any Python? It freaks the HELL out of me; it’s asymetrical…
I SOOO want to put a } or something at the end of a function definition
or other block.

As a concrete example - one of the most common ‘beginner’ questions on
the group is ‘why do I segfault when I SDL_FreeSurface() the display
surface’ - programmers (well, C programmers) seem to expect symmetry,
so there is potentially benefit to providing certain operations that
maybe aren’t strictly necessary…

But what about using function-style macros?

Yeah, that, or (if we assume C99) even inline functions - but to me,
and apparently, quite a few others on this list, it’s just extra
typing for the application coder.

Besides, if it’s implemented like that, there’s no binary level
abstraction, so there goes (IMHO) the only real advantage. Sure, it’s
as fast as what we do now, but the only “bonus” is us doing some
extra typing, so… :wink:

True, but then, let’s face it, you’re working at such a low level,
that virtually any change you make to the implementation risks
breaking binary compatibility. The only change you can make behind an
opaque object is to add members to the end of the struct, which you
can’t do if you have open structs.

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.)
How so?

Well, this is actually going one step further, so it’s not really
about opaque pointers.

Anyway, I’ve done a few APIs using opaque handles (internal table
indices and the like), and they’re kind of handy in small, simple
applications; you can do things like passing -1 for “all objects” and
stuff, and it’s trivial to deal with ranges of objects.

Beyond that however, they offer little more than making certain
mistakes easier to track. Actually, with proper debugging tools (like
Valgrind), this design makes applications harder to debug than
direct pointers, while offering nothing that these tools cannot do
anyway.

So… I can’t really think of any good reason to recommend this kind
of design for anything. It doesn’t really help C and the like, and a
high level language can usually offer much better solutions anyway.

Hmm… I’ve looked into this. I think that, as long as your handles are
actually pointers (rather than arbitrary or obfuscated values) then
modern debuggers can cope. For example, in GDB, you can have an opaque
struct and as long as you have full debugging info (in the lib + app)
you can examine the members of the structures as if the object were open.

GDB also supports ‘invoking’ of preprocessor macros, so you can
comfortably examine the members of an opaque structure.

[…]

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:
Again, goes back to the library trade-off and the shifting
responsibilities thing; if 99% users of your library are going to do
something you didn’t do because of ‘efficiency’ concerns, then
you’re not actually saving anything.
[…]

Well, let’s turn it around a bit: Who needs to access the information
at all? And, what level of “safety” is required for those who do
need access?

As most people won’t need to touch the fields of an SDL_Surface
anyway, why not replace the SDL_Surface pointers throughout
the “normal” API with an opaque pointer type. (Give them
SDL_SurfaceWidth() etc; only what’s really needed.)

Then offer a typecast macro that returns essentially a pointer to the
current SDL_Surface. The declarations for this could be in a separate
header that isn’t included in “normal” applications.

That way, us hardcore low level guys can have it our way, and you can
have your build scripts yell att untrusted programmers if they ever
try to use that typecast macro. :wink:

Yeah, that’s the scheme used in Xlib… I think that providing SDL_Debug
macros or a including a header with the full definition would be a fair
compromise, given the low-level nature of SDL.

I think this discussion has run its course, so I’m gonna crack-on with
it and see what comes out of the other end…

Eddy> A: If function SDL_Xyz() can be implemented in a separate