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

Add support for .NET Standard 2.0 #1

Merged
merged 6 commits into from Jan 31, 2019

Conversation

Projects
None yet
1 participant
@Daniel15
Copy link
Owner

Daniel15 commented Jan 31, 2019

This adds support for .NET Standard 2.0 / .NET Core 2.2.

The trickiest part of this was the handling of the library file name. The file name differs on Windows (libgpgme-11.dll) vs on Linux (libgpgme.so.11). Mono has a feature called "dllmap" which makes this remapping quite easy to perform:

<dllmap dll="libgpgme-11.dll" target="libgpgme.so.11" />

However, this same functionality is not available in .NET Core. Work is currently underway to have some sort of native library loader functionality that would support this (see dotnet/corefx#32015), but as of now, it's not available.

This means I had to hack around it. My initial approach was going to be to have two classes (one for Windows, one for Linux) that implement a common interface:

interface INativeMethods {
    IntPtr gpgme_check_version(IntPtr req_version);
}

class LinuxNativeMethods : INativeMethods {
    [DllImport("libgpgme.so.11", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
    internal extern IntPtr gpgme_check_version([In] IntPtr req_version);
}

class WindowsNativeMethods : INativeMethods {
    [DllImport("libgpgme-11.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
    internal extern IntPtr gpgme_check_version([In] IntPtr req_version);
}

However, DllImport methods must be static, and C# doesn't allow static methods on an interface.

Because of this, my approach ended up being quite hacky: I have one class with the Linux methods, one class with the Windows methods, and a wrapper class that has properties for each of them (see NativeMethodsWrapper.cs).

There was another issue: I wanted to avoid copying-and-pasting the P/Invoke code, however .NET doesn't let you have the same file twice in the same assembly, with two different sets of preprocessor values. So, the Windows and Linux classes needed to be in two separate assemblies.

I updated the build to use ILRepack to merge all the assemblies together, so users shouldn't actually notice any of this hackiness. Ideally this will all be cleaned up once dotnet/corefx#32015 is completed.

Daniel15 added some commits Jan 30, 2019

Add support for .NET Standard 2.0
- Fix handling of library on Linux. Unfortunately, .NET Core doesn't support DllMap like Mono does, so we need to compile the P/Invokes twice (once for Windows, once for Linux) and have an ugly wrapper class as a facade
- Convert gpgme-sharp.csproj to new project file format
- Convert gpgme-sharp.sln to Visual Studio 2017 format

@Daniel15 Daniel15 merged commit 8dc3117 into master Jan 31, 2019

@Daniel15 Daniel15 deleted the dotnetcore branch Jan 31, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment