簡體   English   中英

在 64 位系統上與 gcc 構建的 DLL 互操作上出現 BadImageFormatException

[英]BadImageFormatException on interop from DLL build with gcc on 64-bit system

我正在開發一個 .NET 庫。 作為使庫跨平台的任務的一部分,我決定將所有特定於平台的函數放入 C 文件並構建 DLL(適用於 Windows)和 dylib(適用於 macOS)。 為了開始這個任務,我創建了一個簡單的測試應用程序:Windows 上的控制台應用程序在 .NET 框架上,它從生成的 Z50584E40D2716 調用一個簡單的 function。

C 文件的內容 DLL (test.dll) 構建自:

int Foo() { return 123; }

測試程序代碼:

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();
    }
}

當我運行程序時,我得到BadImageFormatException

如果我 go 在 Visual Studio 中的項目設置,我看到:

在此處輸入圖像描述

如果我在下拉列表中取消選中“首選 32 位”或 select x64,一切都很好,我看到正確的 output:

Result = 123
Press any key to exit...

但這對我來說不是解決方案。 該庫被許多用戶使用,我不想(也不能)強迫他們進行一些環境設置,比如選擇目標平台。 它也應該適用於 x86 和 x64。

DLL 是用 gcc 構建的:

gcc -v -c test.c
gcc -v -shared -o test.dll test.o

我的問題是如何處理問題並創建可以在任何 .NET 應用程序中定位的 DLL,而無需采取初步行動? 也許可以構建具有雙平台目標(不僅是 x64)的 DLL?

我最終構建了兩個版本的 DLL,32 位和 64 位。 所以在代碼中我們有這樣的類:

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;
            }
        }
    }
}

因此,如果我們要調用Method方法,我們將編寫:

var result = ApiProvider.Api.Method();

當然,我們需要在 output 中有以下文件:

  • test32.dll(還有dylib等)
  • test64.dll(還有dylib等)

使用此系統,程序將 select 所需文件取決於當前進程是否為 64 位。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM