使用 MSVC 的 cl 创建 DLL

Creating a DLL using MSVC's cl

我试图了解构建和 linking 的工作原理,因为有一个库我想编译成 DLL。我无法控制将用于编译的工具 - 这将是通过命令行调用的 msvc 工具。

为此,我设法找到了 a tutorial on creating DLLs that does not use Visual Studio。它适用于 mingw,但我设法让它与 cl

一起使用

我已经成功翻译了部分流程以与 msvc 工具一起使用:

gcc -c -o add.o add.c -D ADD_EXPORTS

被翻译成

cl /c /D ADD_EXPORTS add.c

我无法完全翻译以下行:

gcc -o add.dll add.o -s -shared -Wl,--subsystem,windows

但以下方法有效:

link /DLL /NOENTRY add.obj

并创建了 .exp.lib.dll 文件。 -s 开关似乎并不重要(它删除了一些信息,所以我猜最坏的情况是我会得到一个稍大的文件)

然后我设法从 addtest.c 创建了一个 .obj 文件,link 它(针对 .lib 文件),并得到了一个 .exe只要 dll 将它放在同一个文件夹中,它就可以完美运行。

关于更难的问题:The library I ultimately want to have compiled 在玩弄 #includes 并四处移动一些文件以确保每个人都能找到他们的 header 之后,我编译了每个源文件(对于 windows - 据我了解,_WIN32 在预处理时自动定义)和我做的一样 add.c (没有 ADD_EXPORTS),加上我自己的文件,叫做 Source.cpp (我没有创建 header为此)

#include "serial/serial.h"
#include <combaseapi.h>

using serial::Serial;
using std::string;
using std::vector;
using serial::PortInfo;
Serial* sp = NULL;

extern "C" {

    __declspec(dllexport) bool __cdecl createConnection(const char* port, uint32_t baudrate)
    {
        try {
            sp = new Serial(port, baudrate);
            return true;
        }
        catch (...)
        {
            return false;
        }
    }
}

在将它们全部制作成 .obj 文件后,我尝试调用 linker,使用我生成的所有 .obj 文件,使用 link /DLL /NOENTRY Source.obj list_ports/list_ports_win.obj win.obj serial.obj

为此我得到了 134 errors

关于如何在没有 visual studio 的情况下创建 DLL 的信息似乎非常稀缺,而且我找不到任何关于我查找的错误的有用信息(查找时找不到常见错误错误 + 符号)

这里有什么问题?

编辑:感谢一条评论,我设法发现我在 linking 到 CRT 库时遇到问题。 This 帮助我减少了错误的数量,我会看看我是否能弄清楚我得到的新输出并进一步编辑

新 linking 命令: link /DLL /NOENTRY Source.obj list_ports/list_ports_win.obj win.obj serial.obj /LIBPATH:"C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Redist/MSVC/14.29.30036/x64/Microsoft.VC142.CRT"

编辑 2: 使用 cl /c /clr source_file 编译源文件导致 significantly fewer errors 当 link 未指定 LIBPATH 时。我想我什至可以自己解决所有这些问题。稍后我会继续努力。

注意连载最后一个正式版(v1.2.1)发布于2015年4月(20150422),activity 从那以后显着下降。

在继续之前请检查 [SO]: Linking to CRT (unresolved external symbol WinMainCRTStartup) (@CristiFati's answer)(刚刚发布)。

我刚刚构建了包并将工件放在[GitHub]: (master) CristiFati/Prebuilt-Binaries - Prebuilt-Binaries/Serial/v024f80634f40073a41be43e956b5ebaca17f6167(原始代码只构建了一个静态库,我增强它也构建了一个动态库)。按照下载和“安装”说明进行操作。

尝试的方案是从您的源代码构建一个 .dll,它使用下载的 Serial 库。

输出:

[cfati@CFATI-5510-0:e:\Work\Dev\Whosebug\q071859149]> sopr.bat
### Set shorter prompt to better fit when pasted in Whosebug (or other) pages ###

[prompt]> "c:\Install\pc032\Microsoft\VisualStudioCommunity19\VC\Auxiliary\Build\vcvarsall.bat" x64 >nul

[prompt]> dir /b
Source.cpp

[prompt]> set LIBSERIAL_DIR=c:\Program Files\WjwWood\Serial4f80634f40073a41be43e956b5ebaca17f6167

[prompt]> :: Build with static libserial
[prompt]> cl /nologo /I"%LIBSERIAL_DIR%\include" /EHsc /MD /c Source.cpp /FoSource_stat.obj
Source.cpp

[prompt]> link /NOLOGO /DLL /LIBPATH:"%LIBSERIAL_DIR%\lib" Source_stat.obj libserialstatic.lib
   Creating library Source_stat.lib and object Source_stat.exp

[prompt]> dir /b
Source.cpp
Source_stat.dll
Source_stat.exp
Source_stat.lib
Source_stat.obj

[prompt]> :: Build with dynamic libserial
[prompt]> cl /nologo /I"%LIBSERIAL_DIR%\include" /EHsc /MD /DLIBSERIAL_DYNAMIC /c Source.cpp /FoSource_dyn.obj
Source.cpp

[prompt]> link /NOLOGO /DLL /LIBPATH:"%LIBSERIAL_DIR%\lib" Source_dyn.obj libserial.lib
   Creating library Source_dyn.lib and object Source_dyn.exp

[prompt]>
[prompt]> dir
 Volume in drive E is SSD0-WORK
 Volume Serial Number is AE9E-72AC

 Directory of e:\Work\Dev\Whosebug\q071859149

22/04/15  01:58    <DIR>          .
22/04/15  01:58    <DIR>          ..
22/04/15  01:50               394 Source.cpp
22/04/15  01:58            17,920 Source_dyn.dll
22/04/15  01:58               704 Source_dyn.exp
22/04/15  01:58             1,778 Source_dyn.lib
22/04/15  01:57            47,856 Source_dyn.obj
22/04/15  01:55            41,472 Source_stat.dll
22/04/15  01:55               707 Source_stat.exp
22/04/15  01:55             1,790 Source_stat.lib
22/04/15  01:55            46,299 Source_stat.obj
               9 File(s)        158,920 bytes
               2 Dir(s)  24,132,493,312 bytes free

2 个生成的 .dll 之间的“图形”比较。请注意,与 libserial.lib 链接的变体需要 libserial.dll: