【问题标题】:Bizarre System.BadImageFormatException when trying to import C++ dll into C#尝试将 C++ dll 导入 C# 时出现奇怪的 System.BadImageFormatException
【发布时间】:2018-10-25 21:48:36
【问题描述】:

这里是相关的 C# 位

KrautVK.cs

internal static class KrautVK{
    [DllImport("lib\\krautvk", CallingConvention = CallingConvention.Cdecl, EntryPoint = "init")]
    internal static extern int Init(int width, int height, string title, bool fullscreen);

    [DllImport("lib\\krautvk", CallingConvention = CallingConvention.Cdecl, EntryPoint = "windowShouldClose")]
    [return: MarshalAs(UnmanagedType.Bool)]
    internal static extern bool WindowShouldClose();

    [DllImport("lib\\krautvk", CallingConvention = CallingConvention.Cdecl, EntryPoint = "pollEvents")]
    internal static extern void PollEvents();

    [DllImport("lib\\krautvk", CallingConvention = CallingConvention.Cdecl, EntryPoint = "terminate")]
    internal static extern void Terminate();
}

这是(相关的)C++ 代码:

KrautVK.h

#ifndef KRAUTVK_H_
#define KRAUTVK_H_

#include <cstdio>
#include <vector>
#include <iostream>

#define GLFW_INCLUDE_VULKAN
#include <GLFW/glfw3.h>


#define EXPORT extern "C" __declspec(dllexport)

...

EXPORT int init(int w, int h, char *title, int f);

EXPORT int windowShouldClose();

EXPORT void pollEvents();

EXPORT void terminate();

我非常清楚,如果构建格式不匹配(即从 64 位应用程序调用 32 位 dll),DllImport 可能会抛出 System.BadImageFormatException。然而,这种情况并非如此。两者都是针对同一个 CPU 构建的。

在做了一些故障排除后,我发现它完全是由 iostreamvector 包含引起的。通过删除这些包含,错误消失并且调用工作。事实上,在我开始实现需要这些包含的代码之前,我没有遇到任何问题。但是,我需要这些内容,而且一天的研究中大部分都没有找到任何文件或解释这种奇怪的行为,事实上许多例子都使用iostream

如果相关的话,我同时使用 Jetbrains Rider 和 Clion。

【问题讨论】:

  • 两者都是构建并针对相同的 CPU -- 你是如何确定这一点的,即你最终得到的实际上是 32 位二进制文​​件?另外,the answers here do not just talk about "bitness"
  • 首先,在我开发的两个 IDE 中都可以清楚地观察到构建目标,并且作为一项附加措施,我使用了 dumpbin 来检查 dll 的文件头。另外,正如我在问题中已经说过的那样,删除包含 iostreamvector 的错误以某种方式消失了。这与构建目标无关。
  • 我知道位不是System.BadImageFormatException 的唯一原因,并且不打算暗示这样。显然它与那些包含有关,但我还没有找到文档或导致问题实际是什么。
  • 为什么不看看它是否与使用运行时库有关?使用 vectoriostream 需要使用正确的运行时库。这是链接中给出的其他答案之一。
  • C++ DLL 的依赖项是什么? (我使用 Dependency Walker)。它们中的任何一个都是 Visual C++ 运行时吗?如果缺少 DLL,最简单的方法是将它们放在与可执行文件相同的文件夹中。

标签: c# c++ dllimport


【解决方案1】:

使用 Dependency Walker,我缺少 3 个 dll:

  • libstdc++-6.dll
  • libgcc_s_seh-1.dll
  • 和 libwinpthread-1.dll

如果您使用 MingW 环境,它们是必需的运行时库。将它们放入可执行文件夹中就可以了。可以在{Your MingW/MingW64 installation folder}\bin找到它们

【讨论】:

  • 这不是真正的问题,缺少的 DLL 不会导致 BadImageFormatException。您需要找到这些 DLL 的 other 副本(或多个副本)来修复您的机器。通常是通过混乱的 PATH 环境变量或 OS 目录中的杂散副本意外发现的。首先使用 where 命令。
  • 我的 PATH 是为 C++ 开发而设置的,但我将其视为发布版本,即大多数用户没有 MingW64,PATH 指向提供的运行时,所以我需要提供这些 dll。因此,为什么在可执行文件中进行测试但从它作为 dll 访问绑定却失败了。更多信息在这里:stackoverflow.com/questions/18138635/….
  • 在某些情况下,缺少 DLL 可能会导致 BadImageFormatException。请参阅此处以获取另一个案例示例stackoverflow.com/questions/2728560/…
猜你喜欢
  • 2021-04-12
  • 1970-01-01
  • 2013-04-26
  • 1970-01-01
  • 2021-07-13
  • 1970-01-01
  • 1970-01-01
  • 2021-12-02
  • 1970-01-01
相关资源
最近更新 更多