-
Notifications
You must be signed in to change notification settings - Fork 5.4k
Not possible to DllImport a native assembly with a "." in its file name #10007
Description
Since our tooling doesn't support customers to compile for each OS, it currently isn't possible to name a native assembly using namespace names, like "Microsoft.Foo.Bar", and use the assembly in a DllImport successfully on both Windows and non-Windows.
Repro:
Create a native assembly named Test.Foo. On Windows it is named Test.Foo.dll. On Linux it is named Test.Foo.so. On macOS it is named Test.Foo.dylib.
It is not possible to create a C# DllImport into this native assembly from a single managed assembly.
On Windows, if you use:
internal const string NativePath = "Test.Foo";
[DllImport(NativePath)]
public static extern bool Bar();You get an error:
System.DllNotFoundException : Unable to load DLL 'Test.Foo': The specified module could not be found. (Exception from HRESULT: 0x8007007E)
So you need to use Test.Foo.dll in order for Windows to load it.
However, doing this causes it to fail on non-Windows. On non-Windows if you use:
internal const string NativePath = "Test.Foo.dll";
[DllImport(NativePath)]
public static extern bool Bar();You get the error:
System.DllNotFoundException: Unable to load shared library 'Test.Foo.dll' or one of its dependencies. In order to help diagnose loading problems, consider setting the LD_DEBUG environment variable: libTest.Foo.dll: cannot open shared object file: No such file or directory
Using strace, it shows that we are not stripping the .dll off of the name during probing:
open("/mnt/shared/TestML/runtimes/linux-x64/native/Test.Foo.dll.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/home/eerhardt/dotnet/shared/Microsoft.NETCore.App/2.1.0-preview3-26322-05/Test.Foo.dll.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/mnt/shared/TestML/Test.Foo.dll.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 82
fstat(82, {st_mode=S_IFREG|0644, st_size=95952, ...}) = 0
mmap(NULL, 95952, PROT_READ, MAP_PRIVATE, 82, 0) = 0x7ff76fd9f000
close(82) = 0
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
open("/lib/x86_64-linux-gnu/Test.Foo.dll.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/usr/lib/x86_64-linux-gnu/Test.Foo.dll.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/lib/Test.Foo.dll.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/usr/lib/Test.Foo.dll.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
munmap(0x7ff76fd9f000, 95952) = 0
open("/mnt/shared/TestML/runtimes/linux-x64/native/libTest.Foo.dll.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/home/eerhardt/dotnet/shared/Microsoft.NETCore.App/2.1.0-preview3-26322-05/libTest.Foo.dll.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/mnt/shared/TestML/libTest.Foo.dll.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 82
fstat(82, {st_mode=S_IFREG|0644, st_size=95952, ...}) = 0
mmap(NULL, 95952, PROT_READ, MAP_PRIVATE, 82, 0) = 0x7ff76fd9f000
close(82) = 0
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
open("/lib/x86_64-linux-gnu/libTest.Foo.dll.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/usr/lib/x86_64-linux-gnu/libTest.Foo.dll.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/lib/libTest.Foo.dll.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/usr/lib/libTest.Foo.dll.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
munmap(0x7ff76fd9f000, 95952) = 0
open("/mnt/shared/TestML/runtimes/linux-x64/native/Test.Foo.dll", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/home/eerhardt/dotnet/shared/Microsoft.NETCore.App/2.1.0-preview3-26322-05/Test.Foo.dll", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/mnt/shared/TestML/Test.Foo.dll", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 82
fstat(82, {st_mode=S_IFREG|0644, st_size=95952, ...}) = 0
mmap(NULL, 95952, PROT_READ, MAP_PRIVATE, 82, 0) = 0x7ff76fd9f000
close(82) = 0
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
open("/lib/x86_64-linux-gnu/Test.Foo.dll", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/usr/lib/x86_64-linux-gnu/Test.Foo.dll", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/lib/Test.Foo.dll", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/usr/lib/Test.Foo.dll", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
munmap(0x7ff76fd9f000, 95952) = 0
open("/mnt/shared/TestML/runtimes/linux-x64/native/libTest.Foo.dll", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/home/eerhardt/dotnet/shared/Microsoft.NETCore.App/2.1.0-preview3-26322-05/libTest.Foo.dll", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/mnt/shared/TestML/libTest.Foo.dll", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 82
fstat(82, {st_mode=S_IFREG|0644, st_size=95952, ...}) = 0
mmap(NULL, 95952, PROT_READ, MAP_PRIVATE, 82, 0) = 0x7ff76fd9f000
close(82) = 0
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
open("/lib/x86_64-linux-gnu/libTest.Foo.dll", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/usr/lib/x86_64-linux-gnu/libTest.Foo.dll", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/lib/libTest.Foo.dll", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/usr/lib/libTest.Foo.dll", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
munmap(0x7ff76fd9f000, 95952) = 0
Possible solution
We could add another variation on non-Windows that stripped the .dll off of the library name, and then append .so or .dylib to it. This would allow the name Test.Foo.dll to work on all currently supported platforms.
/cc @jkotas @stephentoub