-
Notifications
You must be signed in to change notification settings - Fork 392
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
C API #1640
Comments
This post has a few useful tips on the section "Binding-Friendly C-APIs". |
I build the C# version of LÖVE, this is fully file about C binding to C# In dealing with these problems, I used some crude methods for reference only:
char errStrBuffer[MaxBuffer];
bool4 exported_function_xxx(.....) {
try {
// xxxxxxxxx
sprint(errStrBuffer, "xxxxx") // set error message
return 1; // no error
} catch (e) {
return 0; // have error
}
}
To simplify the structure, there is a special function to do this use #define int bool4 // return type
char errStrBuffer[MaxBuffer]; // https://github.com/endlesstravel/Love2dCS/blob/master/c_api_src/wrap_love_dll.cpp#L118
bool4 wrap_love_dll_filesystem_newFileData_content(const void *contents, int contents_length, const char *filename, FileData** out_filedata)
{
return wrap_catchexcept([&]() {
FileData *t = fsInstance->newFileData(contents, contents_length, filename);
*out_filedata = t;
});
}
Excuse me for any possible mistake. 😄 Build log: |
Can anyone enlighten me to what a c api specifically would allow? Isn't the c++ already established a sufficient api? Or do scripting languages have trouble with c++ apis? |
C++'s ABI makes it practically impossible for any other language to use functions and methods directly from a C++ library. On the other hand, C's ABI is simple and consistent and almost every language supports some form of calling C code from the language (for example LuaJIT's FFI). C wrappers of love's functions are necessary for any use of love outside of its existing hand-written Lua wrapper code. |
I see, so we just need functions that can wrap the classes used in love since runtime ABI interfacers like FFI doesn't support classes. |
Is there any intention of making love objects available as anything but opaque handles / void*? That seems like the most straightforward solution, in which case all typechecking would be done internally anyway. A function such as |
Yeah I suppose you're right. I've been thinking in terms of having those checks be at the language binding level because that's how it's done right now and different languages have different type safety guarantees, but that's probably the best approach even if it'll add error checks to pretty much every API. |
I made an attempt at porting https://github.com/Ruin0x11/love/tree/c-api My methodology was to take the code in the I think having LÖVE available for languages like C#, Ruby or Rust would be very interesting. I was always frustrated by "game engine" frameworks in other languages that are really just low-level bindings to SDL/OpenGL/etc., and ones like MonoGame with unwieldy asset pipelines that overcomplicate things. |
A lot of C wrapper APIs don't actually do a ton of type checking and pass things around as opaque pointers. I feel like it's safe to assume that if you're savvy enough to be using bindings for LÖVE from a separate language it's acceptable to get a segfault/panic if you try to canvas-clear an audio source. A lot of C APIs end up getting wrapped over for a given language rather than used directly (e.g. especially in OOP languages like Crystal or C# people tend to write elaborate class wrappers over the imperative C stuff), so type checking, if it's provided, can probably be done in a per-language way rather than with a lot of guarding code LÖVE-side. |
Is this being worked on currently? I'm interested in this feature so I think I might take a stab at it |
I don't think anyone's actively working on it right now - @Ruin0x11's stuff (above) might be one place to start from, although I'd base it on the 12.0-development branch instead of main. |
What is currently exposed in love.dll? A first step could be to document an unstable "as-is" ABI for those looking to "hack" functionality anyways willing to work around quirks. |
The main C API that's exposed is As for C++, love's C++ headers change almost every week and aren't exactly authored with external use in mind (they even get stripped from the library's exported symbols I believe), it doesn't seem very beneficial for C API work to document a particular iteration of them - and anyone who wants to try using them with a matching C++ compiler will likely need to look at / be familiar with the source code regardless, because of those earlier points. |
A plain C external API for LÖVE would be useful. It would allow any number of other languages to be used to write LÖVE code, and it would make it easier to improve performance of LÖVE code in Lua via LuaJIT's FFI.
That being said, it would also be a lot to maintain. Ideally all of the existing Lua wrapper code would call the new C APIs, to keep consistency.
There are a number of problems to solve and questions to answer when implementing a C API. A few I can think of off the top of my head:
Errors are currently propagated to the Lua wrapper code via C++ exceptions. C APIs would need to return an error status (perhaps also with a thread-local GetLastErrorMessage API) or some other mechanism, instead. Ideally the only exceptions in any of LÖVE's code would be inside constructors and they would be caught and converted as early as possible, but that's more for future convenience rather than necessary for a C wrapper.
Some of the argument and return value types used in the C++ API are not directly C compatible, for example
std::vector
andstd::string
. Those should be wrapped cleanly, somehow.LÖVE's enums are usually declared inside class code, or inside namespaces if not classes. They'll either need to be duplicated for the C wrapper, or moved to separate C files included by both the C++ code and C wrapper.
How will sub/superclass method flexibility interact with type safety? For example how will the equivalent of
Object:release
be defined (would it accept a base type, or would a separate Release function be declared for each type? If the former, is there anything preventing the wrong object type from being passed to other functions?)C has no namespaces, so there should be a well-defined naming convention. Should the equivalent of
Texture:getWidth
contain the Graphics namespace name (e.g.loveGraphicsTextureGetWidth(Texture *tex);
), or not (e.g.loveTextureGetWidth(Texture *tex);
)?Many LÖVE APIs have several function variants. C has no function overloading. Different variants will generally need uniquely named functions, but I'd also like to cut back on 'convenience' variants in favour of keeping the API smaller, for the C API. It might make sense to create extra convenience functions in some cases for common variant functionality.
All LÖVE objects use reference counting. This will need to be exposed directly in the C API, while still keeping it automatic in Lua bindings.
The text was updated successfully, but these errors were encountered: