-
Notifications
You must be signed in to change notification settings - Fork 478
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add symbol lookup functions for dfsdl and dfimg #4757
base: develop
Are you sure you want to change the base?
Conversation
do you actually need the address of the function instead of an API to call through to that function (the pattern for all the existing DFSDL functions)? |
I don't know how many I will ultimately need and the list may change:
|
it's fine to extend the DFSDL API as needed. you might want to refactor to reduce the boilerplate if you'll be adding so many functions, though. |
I'm not opposed to adding something like this for development/debugging purposes, but any code we integrate should call out to "proper" functions defined in DFSDL so that future code can benefit from having those functions available. |
I don't object to adding these to DFSDL. I guess my only concern would be it might eventually include all SDL functions if there's plugins, etc making lots of use of SDL. |
Do we want DFSDL init() to resolve all SDL functions on startup, including dozens that some component may or not use? What if we did late binding for the functions that aren't common and not used in core?
|
is there any significant resource usage or time penalty? linking symbols should be pretty fast |
Storage should already be allocated, right? A few dozen pointers worth. I'd say no on resource usage. Time to call a few dozen symbol lookups... probably still in the nanoseconds on any modern puter. dlsym and GetProcAddress should be highly optimized. Probably not worth benching. |
Binding everything at init time is almost certainly faster than checking if binding is necessary at call time (i.e. the late bindings you proposed), at least beyond a certain number of calls. dlsym() is not particularly fast. Maybe microseconds, maybe closer to milliseconds with our number of calls. I think the main reason we don't just "bind everything" is the number of stubs that would have to be written manually. C barely offers any way to programmatically generate these stubs; the closest approaches I've seen involve defining function prototypes with macros which can be redefined to process each function in other ways, but the SDL headers aren't defined in that way. C++ will get us closer, but there's still a fair amount of manual effort. |
1138f51
to
34da173
Compare
we can't forward declare enums, so we'll have to include some SDL headers in DFSDL.h?, if want this. :/ |
True, but we also don't technically need to use the enums in the function prototypes. We can substitute the underlying integer types. Do we already do that for the other functions? |
I was hoping we wouldn't have to specify the signatures manually 3 times, and let SDL headers be the canonical source for that. But since we can't forward declare enums, and we don't want to include SDL headers. We will to have a long list of pointer declarations that I was hoping to avoid. The only other alternative that I can think of is to make our own enums: int DFSDL::DFSDL_SetTextureBlendMode(SDL_Texture* texture, DFSDL_BlendMode blendMode) { but I don't think I like that approach. |
Oh, but some functions are, inline, defined in SDL headers. Do we copy and paste those in? |
These two headers from SDL included by DFSDL.h, primarily just define enums aside for a 'setup' header - I don't know if the configuration done by begin_code.h does anything bad to dfhack.
So they aren't pulling in the world. The implementation file only needs:
This assuming we don't do all the declarations ourselves. |
I guess it isn't safe to include any SDL headers in DFSDL.h, since it has this.
oh, but it reverses that at the end. ugh. |
SDL_PointInRect defined in SDL_rect.h, I don't know why that's included there. Wasn't supposed to be. Here:
The out.printerr line never prints the error to my terminal launching with ./dfhack, but std::cerr does See: #4814 |
34da173
to
c77f478
Compare
@lethosor what do you think about including SDL header files in |
We've done that before. I don't really have an issue with it for things like enums. But since SDL is C, defining "stubs" for the enums we need is pretty straightforward, if we don't also need the enum values. |
enum SDL_Keymod; // Can't do this, forbidden. Ok - not forbidden - if specify storage, but
Ok, try this then:
Same error:
I even tried to patch SDL itself by giving it a storage type:
I believe this may work in MSVC, but GCC is being a dick. 'They' claim it is because it requires the storage type for memory allocation, type safety, etc. Well the storage type was provided and the compiler is still throwing a hissy fit. |
It should work? Provided we don't include any SDL headers - I guess that's probably what you were thinking. As I mentioned previously, it would be nice to use SDL headers as the canonical source for the declarations which will catch mismatch errors at compile time, and prevents us from having to repeat ourselves 3 times, instead of twice. And the long list of function pointer decls are a monster. |
Arr. We won't be able to include SDL headers, anywhere, including 3rd party code, plugins if we attempt stubs for enums in the DFSDL header. Speaking of brittle. The more I spend on this, the more I realize headers are gonna be required for sanity. This one is on SDL for making enum definitions pull in too much crap, and C++ for unnecessary type safety restrictions - we don't trust the programmer type crap. |
We can try patching SDL like this: In SDL_keycode.h:
In SDL_scancode.h:
And for SDL_bool defined in SDL_stdinc.h:
Then we can: and include SDL_keymod.h and SDL_blendmode.h without including SDL_stdinc.h which includes quite a bit of stuff. This is compiling and working for me. But this approach doesn't play nicely with 3rd party code unless it uses the same headers. |
This might be our culprit here. Nevermind. Tired I guess.
Nevermind.. sigh |
this isn't entirely true, you can declare an "opaque" enum by declaring the enum with a underlying type (for sizing) but without enumerators (e.g. i actually think the problem here is the use of |
c77f478
to
1d40793
Compare
You're right, we probably don't have to do an explicit runtime binding. The "downside" of using automatic binding is that the load of dfhack itself will fail if SDL doesn't bind, but if that happens we're going to be dead in the water anyway. The main disadvantage is that we won't be able to issue a useful diagnostic, since we'll never get loaded and DF will just continue as if were were not there. In any case, if SDL isn't available at runtime, either DF itself won't be working or Bay12 has done something truly unexpected, so I think we can probably safely switch to using automatic binding for SDL. |
Ok, let's try that switch directly after we get -r2 out so we can beta test it. There will be build system changes that need to happen too, and those are always risky. |
There is a chance that we would need to put in some extra work to get SDL linking properly at build time for everyone, especially on Windows. |
This is good news for plugins, etc. Thanks! |
I don't anticipate an issue as long as the dependencies specified in the DLL specifies the SDL libraries with no pathname or with a relative path name, and the SDL libraries have already been loaded by DF before attempting to map dfhooks is called. Since DF on Windows lists SDL2 and SDL2_image as load-time dependencies, there is no way that DF will ever launch without those basenames already loaded; the app won't launch at all if they can't be loaded. We will need to provide an appropriate |
I want something like this.