从.lib文件创建DLL

时间:2018-10-02 09:40:04

标签: c# visual-studio-2013 dllexport

此问题基于以下帖子:https://stackoverflow.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,并确认没有导出任何函数。所以我写了一个包装类。这里是新的代码示例:

在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结果的屏幕截图: Screenshot of Dependency walker

并且无需取消装饰C ++方法: Dependency walker screenshot without undecorating

3 个答案:

答案 0 :(得分:1)

您可以使用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命令行参数)。

答案 1 :(得分:0)

如果可能,请使用__cdecl。

__ stdcall将在函数名称后添加@parameter_bytes。

答案 2 :(得分:0)

我通过文件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中。通过启用“本机代码调试”并在调试时按暂停来发现这一点。

同时,我找到了一个我要控制的设备的生产者提供的.dll。我使用Dependency Walker分析了.dll,并插入了EntryPoints。现在可以了。感谢您的支持。