I'm developing a .NET library. As a part of the task to make the library cross-platform, I decided to put all platform-specific functions to C file and build DLL (for Windows) and dylib (for macOS). To start the task I've created a simple test app: console application on Windows on .NET Framework that calls a simple function from the generated DLL.
Content of the C file the DLL (test.dll) built from:
int Foo() { return 123; }
Test program code:
class Program
{
[DllImport("test")]
public static extern int Foo();
static void Main(string[] args)
{
var result = Foo();
Console.WriteLine($"Result = {result}");
Console.WriteLine("Press any key to exit...");
Console.ReadKey();
}
}
When I run the program I get BadImageFormatException .
If I go the project settings in Visual Studio, I see:
If I either uncheck 'Prefer 32-bit' or select x64 in the dropdown, all is fine and I see correct output:
Result = 123
Press any key to exit...
BUT that's not a solution for me. The library is used by many users and I don't want (and mustn't) to force them to do some environment setup, like selecting target platform. Also it should work on both x86 and x64.
DLL is built with gcc:
gcc -v -c test.c
gcc -v -shared -o test.dll test.o
My question is how to handle the trouble and create DLL that can be targeted in any .NET app without preliminary actions? Maybe it's possible to build a DLL with dual-platform targeting (not only x64)?
I ended up with building two versions of DLL, 32-bit and 64-bit. So in code we have classes like this:
Api.cs
namespace DualLibClassLibrary
{
internal abstract class Api
{
public abstract int Method();
}
}
Api32.cs
using System.Runtime.InteropServices;
namespace DualLibClassLibrary
{
internal sealed class Api32 : Api
{
[DllImport("test32")]
public static extern int Foo();
public override int Method()
{
return Foo();
}
}
}
Api64.cs
using System.Runtime.InteropServices;
namespace DualLibClassLibrary
{
internal sealed class Api64 : Api
{
[DllImport("test64")]
public static extern int Foo();
public override int Method()
{
return Foo();
}
}
}
ApiProvider.cs
using System;
namespace DualLibClassLibrary
{
internal static class ApiProvider
{
private static readonly bool Is64Bit = IntPtr.Size == 8;
private static Api _api;
public static Api Api
{
get
{
if (_api == null)
_api = Is64Bit ? (Api)new Api64() : new Api32();
return _api;
}
}
}
}
So we if we want to call Method
method, we'll write:
var result = ApiProvider.Api.Method();
And of course we need to have following files in output:
With this system the program will select desired file relying on whether the current process is 64-bit or not.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.