简体   繁体   English

在 64 位系统上与 gcc 构建的 DLL 互操作上出现 BadImageFormatException

[英]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 中有以下文件:

  • test32.dll (and dylib, and so on) test32.dll(还有dylib等)
  • test64.dll (and dylib, and so on) test64.dll(还有dylib等)

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.

相关问题 “在64位计算机上构建之后,'System.BadImageFormatException'类型的第一次机会异常 - “A first chance exception of type 'System.BadImageFormatException' ” after buildint on a 64-bit computer 64位COM dll和C#/。Net应用程序之间的免注册互操作 - Registration-free Interop between a 64-bit COM dll and a C#/.Net application WinServer 64位2012 R2上的Autodesk.Inventor.Interop.dll-未注册接口 - Autodesk.Inventor.Interop.dll on WinServer 64-bit 2012 R2 - interface non registred 如何使用P / Invoke从64位C#应用程序中调用64位C ++ DLL? - How can I use P/Invoke to call a 64-bit C++ DLL from a 64-bit C# Application? 从 32 位 Windows 服务使用 64 位进程外 COM DLL - Using 64-bit out of process COM DLL from 32-bit Windows Serivce 初始化Microsoft Excel互操作(64位)时出错 - Error when initializing Microsoft Excel interop (64-bit) EmguCV 64位构建运行时错误 - EmguCV 64-bit build runtime error 检查非托管 DLL 是 32 位还是 64 位? - Check if unmanaged DLL is 32-bit or 64-bit? 在64位应用程序中使用32位interop dll - Using 32 bit interop dll in 64 bit application 使用Environment.Is64BitProcess从c#应用程序动态调用32位或64位DLL - Dynamically calling 32-bit or 64-bit DLL from c# application using Environment.Is64BitProcess
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM