SDL_LoadFunction 'safe'?

Hello.

void (*fp)(void);
fp = SDL_LoadFunction(handle, “ent_func”);

…when compiled (with warnings), gives the message:

warning: ISO C forbids assignment between function pointer and `void *’

fp = (void (*)(void)) SDL_LoadFunction(handle, “ent_func”);

…gives the message:

warning: ISO C forbids conversion of object pointer to function pointer type

So, is there any way to get the above to work cleanly other than just
switching off the warnings? Surely they’re there for good reasons…

anxiously,
a1

Hello.

void (*fp)(void);
fp = SDL_LoadFunction(handle, “ent_func”);

…when compiled (with warnings), gives the message:

warning: ISO C forbids assignment between function pointer and `void *’

fp = (void (*)(void)) SDL_LoadFunction(handle, “ent_func”);

…gives the message:

warning: ISO C forbids conversion of object pointer to function pointer type

So, is there any way to get the above to work cleanly other than just
switching off the warnings? Surely they’re there for good reasons…

fp = (void (*)())SDL_LoadFunction(handle, “ent_func”);

If your function pointer declaration matches the signature of the actual
function, then it is safe to do thi.

-Sam Lantinga, Senior Software Engineer, Blizzard Entertainment

fp = (void (*)())SDL_LoadFunction(handle, “ent_func”);

If your function pointer declaration matches the signature of the actual
function, then it is safe to do thi.

Actually it isn’t. Unfortunately there is little choice
but to do the non-standard cast when a broken
interface requires it.

In this case (my version of) SDL is broken:

extern DECLSPEC void * SDLCALL SDL_LoadFunction(
void *handle, const char *name);

if one assumes it is supposed to be returning a function pointer.
It should return instead

void (*)(void)

which can be converted to the correct function type
(See ISO C99 6.3.2.3/8)

No doubt, however, SDL is simply reflecting the broken
API it is using underneath, for example unix dlsym()
has this fault. Still, it would be better if SDL did
it right.

BTW: example of platform where this cast fails: MSDOS
and Win 3.1 with certain memory models.

There is no reason to assume data pointers and code
pointers are the same size, or even address the same
kind of memory. This tends to be the case with linearly
addressed von Neumann machines, but C does not assume
such a machine model.On Tue, 2006-02-07 at 10:39 -0800, Sam Lantinga wrote:


John Skaller
Felix, successor to C++: http://felix.sf.net

No doubt, however, SDL is simply reflecting the broken
API it is using underneath, for example unix dlsym()
has this fault. Still, it would be better if SDL did
it right.

SDL_LoadFunction() is somewhat misnamed, since it can be used to load
data symbols, too on any reasonable platform.

BTW: example of platform where this cast fails: MSDOS
and Win 3.1 with certain memory models.

We don’t run on those, and honestly, don’t care about them. We’d have
way more issues than LoadFunction’s return type if we tried to target a
16-bit platform.

–ryan.

No doubt, however, SDL is simply reflecting the broken
API it is using underneath, for example unix dlsym()
has this fault. Still, it would be better if SDL did
it right.

SDL_LoadFunction() is somewhat misnamed, since it can be used to load
data symbols, too on any reasonable platform.

Interesting! I had actually created a function that returns a
pointer to an internal data structure, but I see that’s not
actually necessary.

Thanks to everybody for their thoughts on the subject.

a1

No doubt, however, SDL is simply reflecting the broken
API it is using underneath, for example unix dlsym()
has this fault. Still, it would be better if SDL did
it right.

SDL_LoadFunction() is somewhat misnamed, since it can be used to load
data symbols, too on any reasonable platform.

in that case the correct return type is something like

union SDL_pointer {
	void *data;
	void (*function)(void);
};

BTW: example of platform where this cast fails: MSDOS
and Win 3.1 with certain memory models.

We don’t run on those, and honestly, don’t care about them.

I simply gave those platforms as an example of why standards
conformance is important, to show the standards are not
making gratuitous rules. Well, not all the time anyhow ;(

Many programmers have failed to adhere to proper
conformance and now everyone is paying the price,
in particular the amount of broken C code around
that casts between int and void* is truly amazing –
such casts don’t work on 64 bit Unix platforms.

This includes a number of nice SDL packages I’d very
much like to use, including for example Lillith.
If the author had paid attention to standards instead
of making assumptions the code would just build.

The thing is … software changes very slowly – Code
lives for much longer than you’d think – remember Y2K?
Hardware changes fast, so it’s best not to make too many
assumptions – who knows what cool stuff is going to be
around next year?

Who knows what interesting embedded systems applications
SDL could be used for? I mean, isn’t SDL meant to be
good for games? Oh, and aren’t games things you may want
to run on a console or mobile phone these days? :))On Tue, 2006-02-07 at 16:45 -0800, Ryan C. Gordon wrote:


John Skaller
Felix, successor to C++: http://felix.sf.net

SDL_LoadFunction() is somewhat misnamed, since it can be used to load
data symbols, too on any reasonable platform.

Yes, but you have to know exactly what you’re doing if you try this. :slight_smile:
I believe you have to declare your data dllexport on Windows, for example,
and you’ll have a lovely time trying to support C++ symbols from different
compilers.

-Sam Lantinga, Senior Software Engineer, Blizzard Entertainment

Who knows what interesting embedded systems applications
SDL could be used for? I mean, isn’t SDL meant to be
good for games? Oh, and aren’t games things you may want
to run on a console or mobile phone these days? :))

Generally, there comes a cut off point where a device has to forego most
portable code and use custom software.

A few years ago, it was the Palm Pilot. Now it’s probably cell phones,
or maybe even pre-XBox360 consoles. Next year it’ll be something we
refer to as “embedded” … in these cases, you MAY be able to target
your code at it, but you usually have to sacrifice either functionality
or readability, and it’s just not worth it unless you’re, uh, zlib or
something. It’s better just to write directly to that hardware. That’s
why they call it embedded. :slight_smile:

–ryan.

Yes, but you have to know exactly what you’re doing if you try this. :slight_smile:
I believe you have to declare your data dllexport on Windows, for example,
and you’ll have a lovely time trying to support C++ symbols from different
compilers.

I didn’t say it was easy. :slight_smile:

–ryan.

SDL_LoadFunction() is somewhat misnamed, since it can be used to load
data symbols, too on any reasonable platform.

Yes, but you have to know exactly what you’re doing if you try this. :slight_smile:
I believe you have to declare your data dllexport on Windows, for example,

If you’re crazy enough to export data … :]

and you’ll have a lovely time trying to support C++ symbols from different
compilers.

Which is good thing since they can and do use different
calling conventions … and that’s just i386.

Latest XP64 even uses different calling conventions
for C code than its previous incarnation … argg … :slight_smile:

Anyhow my original comment was simply that:

fp = (void (*)())SDL_LoadFunction(handle, “ent_func”);

isn’t actually strictly ISO conformant and a good compiler would
actually reject the program. gcc 4.x is moving towards
stricter compliance. If there’s a need to cheat or hack
about here, I would seem useful if SDL did the cheating,
rather than the application programmer. I previously suggested
something like:

    union SDL_pointer {
            void *data;
            void (*function)(void);
    };

however it may be possible to do even better, knowing what
functions SDL itself is likely to use, one could provide
some extra convenience by adding variants for those function
types, so the user wouldn’t have to write any casts for
those cases. For example:

typedef void (*SDL_audio_h_cft_2)(struct SDL_AudioCVT *, Uint16)

I have a complete automatically generated list of every
callback function type used by SDL, on a 'per header file’
basis (rather than globally), these types are detected and
generated by my wrapper generator program. I guess I could
try to paste those types together and generate a suitable
union type, if there was any interest. The naming convention
is evident:

SDL_audio_h_cft_2
^

header file name ^^^^^ callback function type + sequence number

There aren’t so many of these for SDL … OpenGL is another
story though … :slight_smile:

BTW: I need these things because my system uses C++ classes
as functions. They can still be used as callbacks, using
the client data pointer and a wrapper (but it messes up
the garbage collector at the moment, if the callbacks
run in a different pthread)On Tue, 2006-02-07 at 22:10 -0800, Sam Lantinga wrote:


John Skaller
Felix, successor to C++: http://felix.sf.net

Yes, I agree. However don’t you think it is still worth attempting
to provide an abstraction layer that works on as wide a class
of platforms as is reasonably convenient?

The argument works the other way too: SDL doesn’t support
more sophisticated platforms either.

Still … I’m amazed at what people actually do get working!On Tue, 2006-02-07 at 22:50 -0800, Ryan C. Gordon wrote:

Who knows what interesting embedded systems applications
SDL could be used for? I mean, isn’t SDL meant to be
good for games? Oh, and aren’t games things you may want
to run on a console or mobile phone these days? :))

Generally, there comes a cut off point where a device has to forego most
portable code and use custom software.


John Skaller
Felix, successor to C++: http://felix.sf.net