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

By-value arguments implicitly passed by reference should be exposed as by-value via trampoline #79

Closed
PathogenDavid opened this issue Oct 22, 2020 · 3 comments
Labels
Area-OutputGeneration Issues concerning the process of generating output from Biohazrd Concept-OutputFriendliness Issues concerning the friendliness of using the Biohazrd output Language-C# Issues specific to C#

Comments

@PathogenDavid
Copy link
Member

Some types in C++ are implicitly passed by reference when they wouldn't be in CLR. As such, we explicitly translate parameters of these type with an extra level of indirection. This frequently leads to some awkward-to-use APIs. We should consider translating these as in parameters instead.

@PathogenDavid PathogenDavid added Area-OutputGeneration Issues concerning the process of generating output from Biohazrd Concept-OutputFriendliness Issues concerning the friendliness of using the Biohazrd output Language-C# Issues specific to C# labels Oct 22, 2020
@PathogenDavid
Copy link
Member Author

This should definitely be optional since it has negative performance implications. #196

It might be better to encourage people to instead generate friendly overloads alongside the less-friendly pointer-centric APIs.

@PathogenDavid
Copy link
Member Author

We should not rely on marshaling and instead use trampolines.

See #236

@PathogenDavid PathogenDavid changed the title Arguments implicitly passed by reference should be translated as in (or ref?) parameters By-value arguments implicitly passed by reference should be exposed as by-value via trampoline Feb 14, 2022
@PathogenDavid
Copy link
Member Author

ref/in is the most obvious way to adapt an API with byval implicit-byref parameters when the marshaler is in use, but it's not technically correct. When an implicit byref is passed, the callee assumes it owns the buffer since the caller is supposed to copy the input on the stack and pass the copy to the callee. Passing by an actual reference will appear to work in some situations, but if the callee writes to the input (which is perfectly legal) it will write to the actual version passed in rather than the copy.

For example, consider the following C++ function:

void ThisMethodTakesImplicitByRef(ImVec4 x)
{
    x.y = 100.f; // Perfectly legal, `x` should be a private copy of whatever was passed in.
}

This would be exposed as the following P/Invoke on win-x64:

[DllImport("Mochi.DearImGui.Native.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "?ThisMethodTakesImplicitByRef@@YAXUImVec4@@@Z", ExactSpelling = true)]
private static extern void ThisMethodTakesImplicitByRef_PInvoke(Vector4* x);

If the trampoline is generated as byref like this:

public static void ThisMethodTakesImplicitByRef(in Vector4 x)
{
    fixed (Vector4* __xP = &x)
    { ThisMethodTakesImplicitByRef_PInvoke(xP); }
}

then calling this function will cause y to be mutated.


In theory using in for a const byval parameter (IE: void ThisMethodTakesImplicitByRef(const ImVec4 x)) is technically incorrect but potentially more efficient, but A) this pattern is considered a bad practice in C++ and is considered a code smell so it should be rare (the author probably mean const ImVec4&) and B) in practice neither MSVC or Clang will use this "optimization" and it's probably not legal according to the C++ spec (although I did not check.)

(It's definitely not legal if there's a copy constructor, but we don't honor those right now anyway.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-OutputGeneration Issues concerning the process of generating output from Biohazrd Concept-OutputFriendliness Issues concerning the friendliness of using the Biohazrd output Language-C# Issues specific to C#
Projects
None yet
Development

No branches or pull requests

1 participant