从 .lib 文件创建 DLL

Create a DLL from a .lib file

本题基于以下post:https://whosebug.com/users/9999861/blackbriar

现在我遇到的问题是每次我想使用 dll 时都会出现 System.EntryPointNotFoundException。异常消息说,在我的 dll 中找不到具有我尝试调用的函数名称的入口点。

这是一个位于 .h 文件中的示例函数:

#ifdef __cplusplus
extern "C"
{
#endif
__declspec(dllexport) int __stdcall LDL_Init(char* code)
...
#ifdef __cplusplus
}
#endif

然后我像这样在 C# 中导入函数:

[DllImport("C:\Path\To\Dll\Example.dll", EntryPoint="LDL_Init", CallingConvention=CallingConvention.StdCall)]

public static extern int LDL_Init( [MarshalAs(UnmanagedType.LPStr)] System.Text.StringBuilder code );

有人知道我做错了什么吗?

下次尝试:

我用 Dependency Walker 分析了生成的 dll,发现没有导出函数。所以我写了一个包装器-class。这里是新的代码示例:

在Library.h中:

int LDL_Init(char* code);

在LibraryWrapper.h中:

#pragma once

    class __declspec(dllexport) LibraryWrapper
    {
    public:
        static int __cdecl LDL_Init(char* code);
    };

在LibraryWrapper.cpp.

#include "Library.h"
#include "LibraryWrapper.h"

int LibraryWrapper::LDL_Init(char* code){
    return LDL_Init(code);
}

在Library.cs中:

[DllImport("C:\Path\To\Dll\Example.dll")]
public static extern int LDL_Init( [MarshalAs(UnmanagedType.LPStr)] System.Text.StringBuilder code );

可悲的是,我在执行程序时得到了相同的结果:好的旧 System.EntryPointNotFoundException...

这里是 Dependency Walker 结果的截图:

并且不取消修饰 C++ 方法:

您可以使用 Microsoft DUMPBIN.EXE 工具检查导出:

> dumpbin /EXPORTS Example.dll
Microsoft (R) COFF/PE Dumper Version 14.14.26433.0
Copyright (C) Microsoft Corporation.  All rights reserved.


Dump of file Example.dll

File Type: DLL

  Section contains the following exports for Example.dll

    00000000 characteristics
    FFFFFFFF time date stamp
        0.00 version
           1 ordinal base
           2 number of functions
           2 number of names

    ordinal hint RVA      name

          2    0 000110C3 LDL_Init = @ILT+190(LDL_Init)
          1    1 00011087 foo = @ILT+130(foo)

  Summary

        1000 .00cfg
        1000 .data
        1000 .idata
        2000 .pdata
        3000 .rdata
        1000 .reloc
        1000 .rsrc
        8000 .text
       10000 .textbss

链接器的任何特殊内容,例如 __declspec(dllexport)#pragma comment(lib, ...) 需要被编译器看到,否则编译器将不知道它们,链接器也不会。对于修改后的头文件,这意味着至少包含一次。

或者,对于模块定义文件 (.def),它需要添加到项目中(或手动添加 /DEF filename 命令行参数)。

如果可能,使用__cdecl。

__stdcall会在函数名后加@parameter_bytes。

我"solved"在文件Library.cs中进行如下调整的问题:

[DllImport("C:\Path\To\Dll\Example.dll", EntryPoint="?LDL_Init@LibraryWrapper@@SAHPEAD@Z")]
public static extern int LDL_Init( [MarshalAs(UnmanagedType.LPStr)] System.Text.StringBuilder code );

字符串 EntryPoint 是基于 Dependency Walker 从我的 dll 中提取的函数名称。之后我遇到了问题,代码的执行停在

return LDL_init(code);

在文件中 LibraryWrapper.cpp。通过启用 "native code debugging" 并在调试时按暂停键发现了这一点。

与此同时,我找到了一个由我要控制的设备的生产商提供的.dll。我用 Dependency Walker 分析了 .dll 并插入了入口点。现在可以了。感谢大家的支持。