stanoddly / DotnetRaylibWasm

Prototype for .NET 7 with Raylib compiled into WebAssembly (wasm)
MIT License
58 stars 7 forks source link

Parsing function pointer types in signatures is not supported #4

Open stanoddly opened 1 year ago

stanoddly commented 1 year ago

The build returns lots of these warnings, which means that this functionality can't be used as it is.

DotnetRaylibWasm
  WasmApp.Native.targets(292, 5): [WASM0001] Could not get pinvoke, or callbacks for method 'Raylib_cs.Raylib::SetTraceLogCallback' because 'Parsing function pointer types in signatures is not supported.'
  WasmApp.Native.targets(292, 5): [WASM0001] Could not get pinvoke, or callbacks for method 'Raylib_cs.Raylib::SetLoadFileDataCallback' because 'Parsing function pointer types in signatures is not supported.'
  WasmApp.Native.targets(292, 5): [WASM0001] Could not get pinvoke, or callbacks for method 'Raylib_cs.Raylib::SetSaveFileDataCallback' because 'Parsing function pointer types in signatures is not supported.'
  WasmApp.Native.targets(292, 5): [WASM0001] Could not get pinvoke, or callbacks for method 'Raylib_cs.Raylib::SetLoadFileTextCallback' because 'Parsing function pointer types in signatures is not supported.'
  WasmApp.Native.targets(292, 5): [WASM0001] Could not get pinvoke, or callbacks for method 'Raylib_cs.Raylib::SetSaveFileTextCallback' because 'Parsing function pointer types in signatures is not supported.'
  WasmApp.Native.targets(292, 5): [WASM0001] Could not get pinvoke, or callbacks for method 'Raylib_cs.Raylib::SetAudioStreamCallback' because 'Parsing function pointer types in signatures is not supported.'
  WasmApp.Native.targets(292, 5): [WASM0001] Could not get pinvoke, or callbacks for method 'Raylib_cs.Raylib::AttachAudioStreamProcessor' because 'Parsing function pointer types in signatures is not supported.'
  WasmApp.Native.targets(292, 5): [WASM0001] Could not get pinvoke, or callbacks for method 'Raylib_cs.Raylib::DetachAudioStreamProcessor' because 'Parsing function pointer types in signatures is not supported.'
  WasmApp.Native.targets(292, 5): [WASM0001] Skipping pinvoke 'Raylib_cs.Raylib::AttachAudioStreamProcessor' because 'Parsing function pointer types in signatures is not supported.'.
  WasmApp.Native.targets(292, 5): [WASM0001] Skipping pinvoke 'Raylib_cs.Raylib::DetachAudioStreamProcessor' because 'Parsing function pointer types in signatures is not supported.'.
  WasmApp.Native.targets(292, 5): [WASM0001] Skipping pinvoke 'Raylib_cs.Raylib::SetAudioStreamCallback' because 'Parsing function pointer types in signatures is not supported.'.
  WasmApp.Native.targets(292, 5): [WASM0001] Skipping pinvoke 'Raylib_cs.Raylib::SetLoadFileDataCallback' because 'Parsing function pointer types in signatures is not supported.'.
  WasmApp.Native.targets(292, 5): [WASM0001] Skipping pinvoke 'Raylib_cs.Raylib::SetLoadFileTextCallback' because 'Parsing function pointer types in signatures is not supported.'.
  WasmApp.Native.targets(292, 5): [WASM0001] Skipping pinvoke 'Raylib_cs.Raylib::SetSaveFileDataCallback' because 'Parsing function pointer types in signatures is not supported.'.
  WasmApp.Native.targets(292, 5): [WASM0001] Skipping pinvoke 'Raylib_cs.Raylib::SetSaveFileTextCallback' because 'Parsing function pointer types in signatures is not supported.'.
  WasmApp.Native.targets(292, 5): [WASM0001] Skipping pinvoke 'Raylib_cs.Raylib::SetTraceLogCallback' because 'Parsing function pointer types in signatures is not supported.'.
chrisdill commented 1 year ago

It might be possible to get this to work by using the previous approach we used for callbacks though not ideal. Do you know any details about why this is not supported?

stanoddly commented 1 year ago

It's mentioned in blazor docs:

image

https://learn.microsoft.com/en-us/aspnet/core/blazor/webassembly-native-dependencies?view=aspnetcore-7.0#c-managed-method-callbacks

Here is the link to the issue: https://github.com/dotnet/runtime/issues/56145

seclerp commented 1 year ago

I think this example shows the complete workaround that works for me.

The main idea is to wrap method address into the unmanaged delegate and then cast to IntPtr:

// emscripten_wrap.c: Native lib with callback propagation, actually wrapper over statically linked emscriptent
// to be able to use it with [DllImport]
// See https://github.com/dotnet/runtime/discussions/81991#discussioncomment-5009635
#include <emscripten.h>

EMSCRIPTEN_KEEPALIVE
void call_emscripten_set_main_loop(em_callback_func func, int fps, int simulate_infinite_loop)
{
  emscripten_set_main_loop(func, fps, simulate_infinite_loop);
}
// Bindings, note the IntPtr pointer type here
public class Emscripten
{
  [DllImport("emscripten_wrap", CallingConvention = CallingConvention.Cdecl)]
  public static extern unsafe void call_emscripten_set_main_loop(IntPtr callback, int fps, int simulateInfiniteLoop);
}
// Callback definition
static readonly delegate* unmanaged<void> CallbackPointer = &Callback;

[UnmanagedCallersOnly]
public static void Callback()
{
  // ...
}
// Callback setup
public static void SetupCallback()
{
   Emscripten.call_emscripten_set_main_loop((IntPtr)CallbackPointer , 0, 1);
}

P.S. Thank you for this titanic work with bringing Raylib-cs to the WASM environment, I'm also stepping through this road and your examples saved me really a huge amount of time!