C
C#16mo ago
ascpixi

❔ Does the import-by-ordinal functionality of DllImport work under NAOT + DirectPInvoke?

I'm having a bit of trouble with importing several functions by their ordinal numbers (for context: I'm challenging myself to create the smallest NAOT executable). For DllImportAttribute.EntryPoint, the docs state:
Indicates the name or ordinal of the DLL entry point to be called.
[...]
Ordinals are prefixed with the # sign, for example, #1.
However, when I try doing the following:
#if USE_ORDINALS
[DllImport("user32.dll", EntryPoint = "#2239")]
#else
[DllImport("user32.dll", EntryPoint = "RegisterClassA")]
#endif
public static extern nint RegisterClass(WindowClassA* lpWndClass);
#if USE_ORDINALS
[DllImport("user32.dll", EntryPoint = "#2239")]
#else
[DllImport("user32.dll", EntryPoint = "RegisterClassA")]
#endif
public static extern nint RegisterClass(WindowClassA* lpWndClass);
...the linker doesn't seem to be able to find the symbol(s):
error LNK2001: unresolved external symbol #2239
error LNK2001: unresolved external symbol #2239
...even though I verified the ordinal for my copy of user32.dll:
8 Replies
ascpixi
ascpixiOP16mo ago
I'm compiling using NAOT and I do have user32.dll included in the DirectPInvoke list, alongside user32.lib being included:
<LinkerArg Include="user32.lib"></LinkerArg>
<DirectPInvoke Include="user32" />
<LinkerArg Include="user32.lib"></LinkerArg>
<DirectPInvoke Include="user32" />
(I also tried specifying it using hex, i.e. #8BF, but that also didn't work)
reflectronic
reflectronic16mo ago
i am guessing it is not implemented and you should file an issue it looks like it's not trivial, you would need to start somewhere here https://github.com/dotnet/runtime/blob/main/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs#L1877-L1884 and implement the support all the way down into the object file writer
ascpixi
ascpixiOP15mo ago
well, it does use ordinals when the .lib file tells it to, so i'm not sure if it makes sense to make an issue for such an edge case (even tho DllImport specifies it can import ordinals) cuz i think this only happens w/ DirectPInvoke (as for non-direct p/invokes it would generate a standard p/invoke stub)
reflectronic
reflectronic15mo ago
yeah, it does not write the correct thing into the import table
ascpixi
ascpixiOP15mo ago
for example for Cabinet.dll it does use the ordinals
ascpixi
ascpixiOP15mo ago
i was thinking of using ordinals for opengl32.dll cuz i'm p sure that file wouldn't ever change anyways lol
Michal
Michal15mo ago
The way ordinal imports work is through linker magic. If you make a simple C file (e.g. void hello(void) { printf("Hello, world!\n"); } and a matching DEF file (e.g. LIBRARY lib\nEXPORTS\n hello @1 NONAME (replace \n with newlines) and compile as cl lib.c /LD /link /def:lib.def you'll get an import library (*.lib) that exports a symbol named hello. you just dllimport the hello from C# side and then pass the import library to linker. linker will match up hello with the ordinal and import as such (leaving no trace of the name hello in the final executable)
Accord
Accord15mo ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.
Want results from more Discord servers?
Add your server