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

(Unmanaged) Structs are not considered blittable by Emscripten / Blazor WASM AOT #61146

Closed
HurricanKai opened this issue Nov 3, 2021 · 10 comments · Fixed by #73310
Closed

(Unmanaged) Structs are not considered blittable by Emscripten / Blazor WASM AOT #61146

HurricanKai opened this issue Nov 3, 2021 · 10 comments · Fixed by #73310
Assignees
Labels
arch-wasm WebAssembly architecture area-Interop-mono
Milestone

Comments

@HurricanKai
Copy link
Member

Description

Unmanaged structs are not considered blittable and therefore cannot be used in pinvoke callbacks.

Reproduction Steps

Attempt to compile code like

public struct S { public int Value; }

[UnmanagedCallersOnly]
public void M(S myStruct) { }

using Emscripten / WASM AOT

Expected behavior

The above code should compile.

Actual behavior

An error is shown, structs are not considered blittable.

Regression?

No response

Known Workarounds

No response

Configuration

Tested on .NET 6 RC2

Other information

No response

@dotnet-issue-labeler
Copy link

I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label.

@dotnet-issue-labeler dotnet-issue-labeler bot added the untriaged New issue has not been triaged by the area owner label Nov 3, 2021
@SingleAccretion SingleAccretion added arch-wasm WebAssembly architecture area-Interop-mono labels Nov 3, 2021
@ghost
Copy link

ghost commented Nov 3, 2021

Tagging subscribers to 'arch-wasm': @lewing
See info in area-owners.md if you want to be subscribed.

Issue Details

Description

Unmanaged structs are not considered blittable and therefore cannot be used in pinvoke callbacks.

Reproduction Steps

Attempt to compile code like

public struct S { public int Value; }

[UnmanagedCallersOnly]
public void M(S myStruct) { }

using Emscripten / WASM AOT

Expected behavior

The above code should compile.

Actual behavior

An error is shown, structs are not considered blittable.

Regression?

No response

Known Workarounds

No response

Configuration

Tested on .NET 6 RC2

Other information

No response

Author: HurricanKai
Assignees: -
Labels:

arch-wasm, untriaged, area-Interop-mono

Milestone: -

@lambdageek
Copy link
Member

lambdageek commented Nov 3, 2021

This is an error from the AOT tasks, maybe? Console sample using Mono works (see https://gist.github.com/lambdageek/f289259398a33cdf19811d2ab4eefd35):

$ dotnet run
Hello, World! from Mono
Called with 42

/cc @radical

@lambdageek
Copy link
Member

lambdageek commented Nov 3, 2021

Note that this is also related to #60639 - in particular we will need to follow the runtime's (updated) per-assembly rules for what is blittable

@lambdageek
Copy link
Member

This could be considered an enhancement.

One current workaround is to pass a pointer to the struct:

public struct S {
    public int i;
}


public class P {
    public static void Main () {
	unsafe {
	    Q (&M);
	} 
    }

    [UnmanagedCallersOnly]
    public unsafe static void M (IntPtr myStruct) {
	ref S s = ref Unsafe.AsRef<S>((void*)myStruct);
	Console.WriteLine ($"Called with {s.i}");
    }

    [DllImport("Foo")]
    public static extern unsafe void Q (delegate *unmanaged<IntPtr,void> fn);
}

And correspondingly use a pointer on the native side:

typedef struct S {
	int i;
} S;

typedef void (*fn)(S* s);

void Q (fn f);

void Q (fn f) {
	S s;
	s.i = 42;
	f (&s);
}

@lewing lewing added this to the 7.0.0 milestone Nov 4, 2021
@lewing lewing removed the untriaged New issue has not been triaged by the area owner label Nov 4, 2021
@HurricanKai
Copy link
Member Author

Given the workaround requires changes to the native side, which isn't always possible (ie binding to standardized or otherwise externally defined APIs), I would not consider this as an enhancement, but rather a missing feature that is important to making interop in WASM fully functional.

@ilonatommy
Copy link
Member

ilonatommy commented Jun 21, 2022

Note that this is also related to #60639 - in particular we will need to follow the runtime's (updated) per-assembly rules for what is blittable

The error still persists. Tried in Blazor wasm app with RunAOTCompilation and OP's code pasted to a class in Counter. Fails on publish. Are we planning to fix it in 7.0?

@lambdageek
Copy link
Member

Are we planning to fix it in 7.0?

I think we should. /cc @lewing @radical

@ilonatommy can you try to get a binlog and the error message? It's presumably something in the WasmAppBuilder task

@radical
Copy link
Member

radical commented Jun 21, 2022

if (!isVoid && !IsBlittable(method.ReturnType))
Error($"The return type '{method.ReturnType.FullName}' of pinvoke callback method '{method}' needs to be blittable.");
foreach (var p in method.GetParameters())
{
if (!IsBlittable(p.ParameterType))
Error("Parameter types of pinvoke callback method '" + method + "' needs to be blittable.");

Assigning to @maraf as he was working on the table generation.

@ilonatommy
Copy link
Member

Sure. So my publish Debug produced:

WasmApp.Native.targets(275,5): Parameter types of pinvoke callback method 'System.Void M(StructsAot_61146_BlazorWasm.Pages.Counter+A+S)' needs to be blittable. 

repro: https://github.com/ilonatommy/StructsAot_61146_BlazorWasm_net7p4

@ghost ghost added the in-pr There is an active PR which will close this issue when it is merged label Aug 3, 2022
@ghost ghost removed the in-pr There is an active PR which will close this issue when it is merged label Aug 15, 2022
@ghost ghost locked as resolved and limited conversation to collaborators Sep 14, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
arch-wasm WebAssembly architecture area-Interop-mono
Projects
Status: Done
8 participants