-
Notifications
You must be signed in to change notification settings - Fork 10.5k
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
Overhaul how the native extension is found, loaded and used #7401
Conversation
The goal of this is to fix grpc#7230. The changes here are: - The layout in the nuget package; the files are now in `/runtimes/{os}/native/{library}` - The filename of each library, which now includes the architecture, e.g `grpc_csharp_ext.x64.dll` - The targets file used to copy those files in msbuild-based projects; note that we now don't build up a folder structure. - The way the functions are found Before this change, on Linux and OSX we used to find library symbols manually, and use DllImport on Windows. With this change, the name of the library file changes based on architecture, so `DllImport` doesn't work. Instead, we have to use `GetProcAddress` to fetch the function. This is further convoluted by the convention on Windows-x86 to prefix the function name with `_` and suffix it based on the stack size of the arguments. We can't easily tell the argument size here, so we just try 0, 4, 8...128. (128 bytes should be enough for anyone.) This is inefficient, but it's a one-time hit with a known number of functions, and doesn't seem to have any significant impact. The benefit of this in code is we don't need the DllImports any more, and we don't need to conditionally use `FindSymbol` - we just use it for everything, so things are rather more uniform and tidy. The further benefit of this is that the library name is no longer tied to a particular filename format - so if someone wanted to have a directory with the libraries for every version in, with the version in the filename, we'd handle that just fine. (At least once Testing: - Windows: - Console app under msbuild, dotnet cli and DNX - ASP.NET Classic under msbuild - ASP.NET Core (still running under net451) - Ubuntu 16.04 - Console app under dotnet cli, run with dotnet run and mono - OSX: - Console app under dotnet cli, run with dotnet run and mono Under dotnet cli, a dependency on `Microsoft.NETCore.Platforms` is required in order to force the libraries to be copied. This change does *not* further enable .NET Core. It attempts to keep the existing experimental .NET Core project files in line with the msbuild files, but I expect further work to be required for .NET Core, which has a different build/publication model.
Thanks for your pull request. The automated tests will run as soon as one of the admins verifies this change is ok to test. |
3 similar comments
Thanks for your pull request. The automated tests will run as soon as one of the admins verifies this change is ok to test. |
Thanks for your pull request. The automated tests will run as soon as one of the admins verifies this change is ok to test. |
Thanks for your pull request. The automated tests will run as soon as one of the admins verifies this change is ok to test. |
Can we change the way the Windows DLL is built to include an exports file? That will eliminate the issue you are having with the automatic names, you can export the functions with any name you want and isolating the calling code from this madness, see .def files here. |
@@ -176,17 +178,18 @@ private static string GetArchitectureString() | |||
// platform specific file name of the extension library | |||
private static string GetNativeLibraryFilename() | |||
{ | |||
string architecture = GetArchitectureString(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You do the platform check twice, inside of GetArchitectureString()
and here. Why not just move the architecture check here and return the hardcoded name of the library? The String.Format
doesn't really gain much in this scenario.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, GetArchitectureString only checks the 32/64-bit aspect; the only platform checks in here are for OS. Did you mean in GetPlatformString? I'm sure there are other ways of doing this, but I was aiming for minimal changes in this PR... this approach works, and the overhead is tiny and one-off.
Good heroic effort :). Sorry for the head aches. |
We may be able to change how the DLL is built in the future, but I don't want to start messing with that right now. The workaround for guessing the name should be fine - if something changes that stops it working, it will break all the tests. It's an implementation detail that can definitely be changed later. |
The "basic tests" failures don't look related to this change, as far as I can tell. |
Seems to me too that the windows loading code could be simplified, but since its not missing out on anything that the DLLImport was getting (both covering stdcall names), this could be done separately. Made an issue for that here #7409 |
LGTM |
@apolcyn: Could you merge, please? I don't have commit permissions on this project. |
Sorry as I haven't been merging things yet, I'm waiting on someone else to merge now. |
I believe the native DLLs on windows are built in the right way - there's two ways to export the symbols - using the .def file or using grpc/src/csharp/ext/grpc_csharp_ext.c Line 49 in bbf2fcd
|
You can specify the name of the exported symbol in the def file with the = On Mon, Jul 18, 2016 at 2:59 AM, Jan Tattermusch notifications@github.com
|
The goal of this is to fix #7230.
The changes here are:
/runtimes/{os}/native/{library}
e.g
grpc_csharp_ext.x64.dll
note that we now don't build up a folder structure.
Before this change, on Linux and OSX we used to find library symbols
manually, and use DllImport on Windows. With this change, the name
of the library file changes based on architecture, so
DllImport
doesn't work. Instead, we have to use
GetProcAddress
to fetch thefunction. This is further convoluted by the convention on
Windows-x86 to prefix the function name with
_
and suffix it basedon the stack size of the arguments. We can't easily tell the
argument size here, so we just try 0, 4, 8...128. (128 bytes should
be enough for anyone.) This is inefficient, but it's a one-time hit
with a known number of functions, and doesn't seem to have any
significant impact.
The benefit of this in code is we don't need the DllImports any
more, and we don't need to conditionally use
FindSymbol
- we justuse it for everything, so things are rather more uniform and tidy.
The further benefit of this is that the library name is no longer
tied to a particular filename format - so if someone wanted to have
a directory with the libraries for every version in, with the
version in the filename, we'd handle that just fine. (At least once
Testing:
Under dotnet cli, a dependency on
Microsoft.NETCore.Platforms
isrequired in order to force the libraries to be copied.
This change does not further enable .NET Core. It attempts to
keep the existing experimental .NET Core project files in line
with the msbuild files, but I expect further work to be required
for .NET Core, which has a different build/publication model.