Skip to content
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 functions for returning default def structs. #110

Closed
BeanCheeseBurrito opened this issue Jan 18, 2024 · 7 comments
Closed

Add functions for returning default def structs. #110

BeanCheeseBurrito opened this issue Jan 18, 2024 · 7 comments

Comments

@BeanCheeseBurrito
Copy link

I am currently working on creating automated C# bindings for box2c at this repo Box2D.NET. Most C# bindings generators do not support generating constant structs like this one below.

static const b2Filter b2_defaultFilter = {0x00000001, 0xFFFFFFFF, 0};

It is left up to the user to initialize the default values manually because of these limitations. Right now I have handwritten extensions that provide the default values but these are error prone and will become outdated if box2c adds/modifies/removes any members from these structs.

It would be great if box2c also came functions that could provide default values as an alternative to using the const structs. Maybe something like b2_MakeDefaultWorldDef would be a good option? Ideally the user should be able use these functions and run the binding generator without having to worry about possible changes to the default values.

@erincatto
Copy link
Owner

I switched to the constants because it makes writing some code nicer, such as

b2BodyId bodyId = b2CreateBody(worldId, &b2_defaultBodyDef);

I cannot do this with a function without passing the function output by value and making a copy. Having both the constant and the function is also not ideal for the reason you mention.

Is there a way to automate these handwritten C# extensions? Or maybe at least validate them when you update?

@BeanCheeseBurrito
Copy link
Author

Is there a way to automate these handwritten C# extensions? Or maybe at least validate them when you update?

Providing functions that return copies of the default structs should be good enough for my use-case. I think most people using/creating bindings will end up just storing a copy in a constant/readonly variable so that you can still do b2CreateBody(worldId, &b2_defaultBodyDef);.

For example, in the extension files I linked in the original post. Instead of doing this:

public static readonly QueryFilter defaultQueryFilter = new QueryFilter
{
    categoryBits = 0x00000001,
    maskBits = 0xFFFFFFFF
};

I would do this and it should be future-proof as long as MakeDefaultQueryFilter isn't renamed.

public static readonly QueryFilter defaultQueryFilter = MakeDefaultQueryFilter();

The main issue right now is that binding generators (non-C# ones too) don't output anything for constants like those, so it's up to the user to eyeball the source code for the correct values. Having these convenience functions will ensure that language bindings at least have access to a copy those default structs. I personally don't mind updating the extensions manually, but this addition would be greatly appreciated!

erincatto added a commit that referenced this issue Feb 20, 2024
default defs from functions

Addresses: #110 and #109
@erincatto
Copy link
Owner

Implemented this in #118. Thanks for your feedback!

@BeanCheeseBurrito
Copy link
Author

Thanks! I'm able to correctly generate bindings for the new functions but I'm unable to obtain entry points to them from the shared library. I'm not very familiar with C, but it looks like adding an extern definition to a .c file seems to fix the issue on my end. Would it be possible to make this change?

// types.h
inline b2QueryFilter b2DefaultQueryFilter()
{
    b2QueryFilter filter = {0x00000001, 0xFFFFFFFF};
    return filter;
}

// types.c
#include "box2d/types.h"
extern inline b2QueryFilter b2DefaultQueryFilter();

@erincatto erincatto reopened this Feb 21, 2024
@erincatto
Copy link
Owner

erincatto commented Feb 21, 2024

How does it handle inline math functions, like b2RotateVector?

I see, this is what raylib does. By putting the extern inline in the source file it can have external linkage.

It looks like SDL C# bindings are converting inline functions:
https://github.com/flibitijibibo/SDL2-CS/blob/1ef072adb1653d3e79fa99586ebcb1797a54caca/src/SDL2.cs#L4226
But this seems to be hand written.

@BeanCheeseBurrito
Copy link
Author

How does it handle inline math functions, like b2RotateVector?

The binding generator is able to read the static inline functions from header files and generate a C# equivalent interface for them like so.

[System.Runtime.InteropServices.DllImport(BindgenInternal.DllImportPath, EntryPoint = "b2RotateVector", CallingConvention = System.Runtime.InteropServices.CallingConvention.Cdecl)]
public static extern Vec2 RotateVector(Rot q, Vec2 v);

During runtime, when the function is called, it is unable for find an entry point to the function unless it has an extern declaration in a source file. With the changes, it works like normal.

Unhandled exception. System.EntryPointNotFoundException: Unable to find an entry point named 'b2RotateVector' in shared library 'box2c'.

@erincatto
Copy link
Owner

I think this is resolved in #119.
Please re-open if it isn't working correctly now.
Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants