Useless unmanaged warpers generated when has delegate pointers
Nobody has claimed this yet.
- Dominant language
- C#
- Stars
- 2.5k
- Forks
- 124
- Avg merge
- 1d 3h
- Merged PRs (30d)
- 9
Description
Actual behavior
When a type has delegate pointer, it will add a unmanaged suffix in the name.
WinMD:
[StructLayout(LayoutKind.Auto, CharSet = CharSet.Auto)]
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
public unsafe delegate JNI_ERROR InputJavaVM([In] JavaVM* vm);
[StructLayout(LayoutKind.Auto, CharSet = CharSet.Auto)]
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
public unsafe delegate JNI_ERROR InputJavaVMWithArgs([In] JavaVM* vm, [Out] JNIEnv* penv, [Optional][In] JavaVMAttachArgs* args);
[StructLayout(LayoutKind.Auto, CharSet = CharSet.Auto)]
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
public unsafe delegate int InputJavaVMWithVersion([In] JavaVM* vm, [Out] JNIEnv* penv, [In] JNI_VERSION version);
public struct JNIInvokeInterface
{
public unsafe void* reserved0;
public unsafe void* reserved1;
public unsafe void* reserved2;
public InputJavaVM DestroyJavaVM;
public InputJavaVMWithArgs AttachCurrentThread;
public InputJavaVM DetachCurrentThread;
public InputJavaVMWithVersion GetEnv;
public InputJavaVMWithArgs AttachCurrentThreadAsDaemon;
}
Generated:
[global::System.CodeDom.Compiler.GeneratedCode("Microsoft.Windows.CsWin32", "0.3.264+4d6898735f.RR")]
internal partial struct JNIInvokeInterface_unmanaged
{
internal unsafe void* reserved0;
internal unsafe void* reserved1;
internal unsafe void* reserved2;
internal unsafe delegate *unmanaged[Stdcall]<global::Java.Runtime.Native.JavaVM_unmanaged*,global::Java.Runtime.Native.JNI_ERROR> DestroyJavaVM;
internal unsafe delegate *unmanaged[Stdcall]<global::Java.Runtime.Native.JavaVM_unmanaged*,global::Java.Runtime.Native.JNIEnv*,winmdroot.Runtime.Native.JavaVMAttachArgs*,global::Java.Runtime.Native.JNI_ERROR> AttachCurrentThread;
internal unsafe delegate *unmanaged[Stdcall]<global::Java.Runtime.Native.JavaVM_unmanaged*,global::Java.Runtime.Native.JNI_ERROR> DetachCurrentThread;
internal unsafe delegate *unmanaged[Stdcall]<global::Java.Runtime.Native.JavaVM_unmanaged*,global::Java.Runtime.Native.JNIEnv*,global::Java.Runtime.Native.JNI_VERSION,int> GetEnv;
internal unsafe delegate *unmanaged[Stdcall]<global::Java.Runtime.Native.JavaVM_unmanaged*,global::Java.Runtime.Native.JNIEnv*,winmdroot.Runtime.Native.JavaVMAttachArgs*,global::Java.Runtime.Native.JNI_ERROR> AttachCurrentThreadAsDaemon;
}
I don't know what it is work for, but no one has used the original name.
And the type who use it generated both original and unmanaged one, but the members is same.
WinMD:
public struct JavaVM
{
[Const]
public unsafe JNIInvokeInterface* functions;
}
Generated:
[global::System.CodeDom.Compiler.GeneratedCode("Microsoft.Windows.CsWin32", "0.3.264+4d6898735f.RR")]
internal partial struct JavaVM
{
internal unsafe winmdroot.Runtime.Native.JNIInvokeInterface_unmanaged* functions;
}
[global::System.CodeDom.Compiler.GeneratedCode("Microsoft.Windows.CsWin32", "0.3.264+4d6898735f.RR")]
internal partial struct JavaVM_unmanaged
{
internal unsafe winmdroot.Runtime.Native.JNIInvokeInterface_unmanaged* functions;
}
Some method is using the original one and some is using the unmanaged one:
[DllImport("jvm", ExactSpelling = true),DefaultDllImportSearchPaths(DllImportSearchPath.System32 | DllImportSearchPath.ApplicationDirectory | DllImportSearchPath.AssemblyDirectory)]
internal static extern unsafe winmdroot.Runtime.Native.JNI_ERROR JNI_CreateJavaVM(out winmdroot.Runtime.Native.JavaVM_unmanaged* pvm, winmdroot.Runtime.Native.JNIEnv** penv, winmdroot.Runtime.Native.JavaVMInitArgs* args);
[DllImport("jvm", ExactSpelling = true),DefaultDllImportSearchPaths(DllImportSearchPath.System32 | DllImportSearchPath.ApplicationDirectory | DllImportSearchPath.AssemblyDirectory)]
internal static extern unsafe winmdroot.Runtime.Native.JNI_ERROR JNI_GetCreatedJavaVMs(ref winmdroot.Runtime.Native.JavaVM param0, int param1, int* param2);
And it makes the method which use the original one wrong:
WinMD:
[DllImport("jvm", ExactSpelling = true, PreserveSig = false)]
[StaticLibrary("jvm")]
public unsafe static extern JNI_ERROR JNI_GetCreatedJavaVMs([In][Out] JavaVM** param0, [In] int param1, [Out] int* param2);
Generated:
/// <inheritdoc cref="JNI_GetCreatedJavaVMs(ref winmdroot.Runtime.Native.JavaVM, int, int*)"/>
[OverloadResolutionPriority(1)]
internal static unsafe winmdroot.Runtime.Native.JNI_ERROR JNI_GetCreatedJavaVMs(ref winmdroot.Runtime.Native.JavaVM param0, int param1, out int param2)
{
fixed (int* param2Local = ¶m2)
{
winmdroot.Runtime.Native.JNI_ERROR __result = PInvoke.JNI_GetCreatedJavaVMs(ref param0, param1, param2Local);
return __result;
}
}
[DllImport("jvm", ExactSpelling = true),DefaultDllImportSearchPaths(DllImportSearchPath.System32 | DllImportSearchPath.ApplicationDirectory | DllImportSearchPath.AssemblyDirectory)]
internal static extern unsafe winmdroot.Runtime.Native.JNI_ERROR JNI_GetCreatedJavaVMs(ref winmdroot.Runtime.Native.JavaVM param0, int param1, int* param2);
Expected behavior
Do not add unmanaged suffix if unnecessary.
I see #1545 has add generate wrapper structs for unmanaged delegates. Is that need to set something to enable it?
Repro steps
Use C#/Win32 to generate:
typedef int(_stdcall* MethodPtr)(void* args);
struct TestStruct
{
MethodPtr Method;
};
Context
- CsWin32 version: 0.3.269
- Target Framework: net4.8.1
LangVersion(if explicitly set by project): latest
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the C#/Win32 reproduction involving a struct containing a delegate pointer, then trace how delegate-pointer fields cause unmanaged wrapper structs and suffixed types to be generated. Done means unnecessary unmanaged wrappers are not emitted and generated methods consistently use the appropriate original type.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp
- Domain
- tooling
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100