-
Notifications
You must be signed in to change notification settings - Fork 320
Add zero-argument function for variadic functions #297
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
base: master
Are you sure you want to change the base?
Conversation
This will allow for better compatibility with C#
Why not just use |
Hello, thanks for the fast reply! Indeed! That's what we are doing already in our bindings: And that works in Windows. But it crashes in WebAssembly. In the C side, the function is defined as: CIMGUI_API void igText(const char* fmt, ...) In the C# side the binding is defined as: [DllImport("cimgui", CallingConvention = CallingConvention.Cdecl)]
public static extern void igText([MarshalAs(UnmanagedType.LPUTF8Str)] string fmt); The way variadic arguments are handled is platform dependent. But it has to, somehow, pass the number of arguments. In Windows, the number of arguments would be implicit from the format string. When you call this function in the C# side as The way C# provides for passing variadic args is using the [DllImport("cimgui", CallingConvention = CallingConvention.Cdecl)]
public static extern void igText([MarshalAs(UnmanagedType.LPUTF8Str)] string fmt, __arglist); Unfortunately, as I mentioned earlier, this is only supported in Windows, and the issue has been opened for years :( |
As I am not a C# user, I would like to hear @JunaMeinhold and @zaafar opinions in this issue: Is there any other way to solve it, etc? |
Hi, i had the same issue and tried to workaround it with "hacks" (trying to build the signature on runtime) and that didn't work out so i made a small library to achieve something similar but in pure c# and in the end i came up with this: (copy pasted from my best practices with Hexa.NET.ImGui)
Don’t: int number = 123;
ImGui.Text($"Hello {123} world!"); // Creates unnecessary string allocations String interpolation and ToString calls can lead to increased garbage collection pressure, as they generate new string objects on the heap. Do: byte* buffer = stackalloc byte[128]; // Use a stack-allocated buffer
StrBuilder builder = new(buffer, 128); // Initialize a memory-safe builder
builder.Reset(); // Clear any previous content
builder.Append("Hello "u8); // Append UTF-8 literal
builder.Append(number); // Append number directly
builder.Append(" world!"u8); // Append more text
builder.End(); // Finalize the buffer
ImGui.Text(builder); // Render the content Using stack-allocated buffers and the StrBuilder struct ensures: (Can be found in the nuget package Hexa.NET.Utilities)
https://github.com/HexaEngine/Hexa.NET.Utilities And i tried to implement a printf in c# but never finished it. |
Great thanks for sharing @JunaMeinhold Basically, if I understood correctly, you are using ig.Text first string argument an skiped variadic arguments completely. I still have doubts about:
and so the crashing in WebAssembly? |
I don't use variadic arguments at all, i simply pass a byte* (c equivalent of char*), i simply format the string from c# side using raw pointers with stack allocated memory and then pass it. And __arglist is a undocumented c# feature the way variadic args are handled always varies from compiler to compiler means that there is probably no stable way of making __arglist work since it's closely tied to MSVC and windows. And i also call them differently, i basically load all exported functions up-front and populate a void** table and then cast it to a delegate* which is basically a c function pointer, idk if that works with WASM because it bypasses some C# safety mechanisms. [MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static void TextNative(byte* fmt)
{
#if NET5_0_OR_GREATER
((delegate* unmanaged[Cdecl]<byte*, void>)funcTable[133])(fmt);
#else
((delegate* unmanaged[Cdecl]<nint, void>)funcTable[133])((nint)fmt);
#endif
} |
Hello!
I'm helping maintain ImGui.Net C# binds.
We are having trouble invoking variadic functions such as:
These functions allow passing an arbitrary number of arguments.
The problem is that C# doesn't have good support for calling such native functions.
In Windows it kind of works with some tweaks in the C# side. However, that's the only platform supported.
In WebAssembly, for example, it crashes.
This is issue has been reported to .Net years ago but there is no solution so far.
Also we can't call the
va_list
version of these functions, as the format of that struct is not standardized.The solution we found is to generate a new version of these functions which has zero variadic arguments (e.g igText0).
Fortunately, all the functions that have variadic arguments are for string formatting purposes, so it's not an issue not being able to specify those arguments as C# already has string formatting built it the language.