[英]BadImageFormatException on interop from DLL build with gcc on 64-bit system
I'm developing a .NET library.我正在开发一个 .NET 库。 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).作为使库跨平台的任务的一部分,我决定将所有特定于平台的函数放入 C 文件并构建 DLL(适用于 Windows)和 dylib(适用于 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.为了开始这个任务,我创建了一个简单的测试应用程序:Windows 上的控制台应用程序在 .NET 框架上,它从生成的 Z50584E40D2716 调用一个简单的 function。
Content of the C file the DLL (test.dll) built from: C 文件的内容 DLL (test.dll) 构建自:
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 .当我运行程序时,我得到BadImageFormatException 。
If I go the project settings in Visual Studio, I see:如果我 go 在 Visual Studio 中的项目设置,我看到:
If I either uncheck 'Prefer 32-bit' or select x64 in the dropdown, all is fine and I see correct output:如果我在下拉列表中取消选中“首选 32 位”或 select x64,一切都很好,我看到正确的 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.它也应该适用于 x86 和 x64。
DLL is built with gcc: DLL 是用 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?我的问题是如何处理问题并创建可以在任何 .NET 应用程序中定位的 DLL,而无需采取初步行动? Maybe it's possible to build a DLL with dual-platform targeting (not only x64)?也许可以构建具有双平台目标(不仅是 x64)的 DLL?
I ended up with building two versions of DLL, 32-bit and 64-bit.我最终构建了两个版本的 DLL,32 位和 64 位。 So in code we have classes like this:所以在代码中我们有这样的类:
Api.cs Api.cs
namespace DualLibClassLibrary
{
internal abstract class Api
{
public abstract int Method();
}
}
Api32.cs 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 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 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:因此,如果我们要调用Method
方法,我们将编写:
var result = ApiProvider.Api.Method();
And of course we need to have following files in output:当然,我们需要在 output 中有以下文件:
With this system the program will select desired file relying on whether the current process is 64-bit or not.使用此系统,程序将 select 所需文件取决于当前进程是否为 64 位。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.