C# 包装DLL-了解导入失败的原因

C# 包装DLL-了解导入失败的原因,c#,c++,dll,dllimport,C#,C++,Dll,Dllimport,背景 我有一个嵌入式系统,运行一个C++最初编写的应用程序,并在VisualStudio中编译,这导致一个可执行文件和30个以上的DLL。无法在VS对象浏览器或其他工具(如P/Invoke Interop Assistant)中浏览这些库 在Dependency Walker中加载一些dll表明,所有dll在其依赖关系树(cdfview.dll、dwmapi.dll、w32topl.dll等)的深处都缺少一些依赖关系,但根据,这可能不是问题 我有一些源代码文件,以及所有编译过的DLL。应用程序当

背景

我有一个嵌入式系统,运行一个C++最初编写的应用程序,并在VisualStudio中编译,这导致一个可执行文件和30个以上的DLL。无法在VS对象浏览器或其他工具(如P/Invoke Interop Assistant)中浏览这些库

在Dependency Walker中加载一些dll表明,所有dll在其依赖关系树(cdfview.dll、dwmapi.dll、w32topl.dll等)的深处都缺少一些依赖关系,但根据,这可能不是问题

我有一些源代码文件,以及所有编译过的DLL。应用程序当前运行时没有问题,表明没有真正的依赖性问题

我试图调用一些库函数,并最终使用C#制作包装器,但即使是最简单的函数也无法成功导入和调用。我总是收到以下错误:

无法加载DLL“dllName.DLL”:动态链接库(DLL) 初始化例程失败。(来自HRESULT的异常:0x8007045A)

示例代码[已编辑]

从C++源代码头文件中,我有以下声明:

#define OB_API __declspec(dllexport) __cdecl 

typedef unsigned long DWORD;  // From windef.h
typedef DWORD OBSTATUS;

OBSTATUS OB_API TestObj(void);

在C++源代码文件中给出了下面的定义(它似乎总是返回>Trime>):

在我的C#application类中,我添加了以下声明:

[DllImport(@"dllName.dll", CallingConvention=CallingConvention.Cdecl)
public static extern ulong TestObj();
DLL和C#应用程序二进制文件位于同一目录中

问题

通过对错误的研究,似乎有很多原因可以引发这个特殊的异常,我想知道如何进一步解决这类问题

有没有办法获得初始化例程失败原因的更详细信息


(注意:目标系统正在运行.NET framework 2.0)

正在加载的DLL包含一个DllMain()函数。这很常见,这样的函数初始化DLL的状态。Windows确保每当加载DLL时调用此函数,当您第一次pinvoke该DLL导出的函数时,此函数将自动发生

问题是,该函数返回FALSE,表示它无法正确初始化DLL。当然,这并没有给出关于它为什么返回FALSE的全部信息。Windows只能生成错误1114,错误\u DLL\u INIT\u失败。如果DLL本身没有输出任何诊断,那么除了调试代码外,您什么也做不了。从“项目+属性”的“调试”选项卡开始,勾选“启用非托管代码调试”选项


祈祷您在输出窗口中看到一条消息。可能性不大。如果您没有DLL的源代码,则需要DLL的供应商或作者的帮助。给他一份这样失败的测试项目的副本。

您正在加载的DLL包含一个DllMain()函数。这很常见,这样的函数初始化DLL的状态。Windows确保每当加载DLL时调用此函数,当您第一次pinvoke该DLL导出的函数时,此函数将自动发生

问题是,该函数返回FALSE,表示它无法正确初始化DLL。当然,这并没有给出关于它为什么返回FALSE的全部信息。Windows只能生成错误1114,错误\u DLL\u INIT\u失败。如果DLL本身没有输出任何诊断,那么除了调试代码外,您什么也做不了。从“项目+属性”的“调试”选项卡开始,勾选“启用非托管代码调试”选项


祈祷您在输出窗口中看到一条消息。可能性不大。如果您没有DLL的源代码,则需要DLL的供应商或作者的帮助。给他一份这样失败的测试项目的副本。

那么init失败的原因是因为
DLLMain
返回值?那很有用。我确实有库的源代码,包括“代码> dLMNEX/CODE >的定义,虽然我看不出函数可能返回一个错误值。如果代码是用C或C++编写的,则有一个间接的级别,Windows调用的实际DLLINE()是yDLNMLCRTSTARTUP()。它初始化CRT并调用初始化器,然后调用DllMain()。初始值设定项的失败也会导致错误的返回值,您通常会看到抛出异常。有没有办法知道调用了哪些初始值设定项?我已经检查了代码,但不确定我在寻找什么。我有整个VS项目文件,注意没有为DLL指定入口点-这意味着它应该调用默认的
DllMain
。至于调试器,我不知道如何做到这一点——目标环境没有安装开发软件(非常有限的RAM、CPU)。这里还有另一个想法:我是否也应该从这个库所依赖的库中查找
FALSE
返回值?即使从未调用父函数,是否加载了父库?我暂时没有回答这个问题,希望可以获得更多信息或提示。我猜简单的答案是“它很复杂”,没有单一的方法来解决这些问题。所以init失败的原因是因为
DLLMain
返回值?那很有用。我确实有库的源代码,包括“代码> dLMNEX/CODE >的定义,虽然我看不出函数可能返回一个错误值。如果代码是用C或C++编写的,则有一个间接的级别,Windows调用的实际DLLINE()是yDLNMLCRTSTARTUP()。它初始化CRT并调用初始化器,然后调用DllMain()。初始化失败也会导致错误的返回值,您通常会看到异常获取t
[DllImport(@"dllName.dll", CallingConvention=CallingConvention.Cdecl)
public static extern ulong TestObj();