2

I am attempting to get an understanding of how building and linking works, since there's a library I want to compile into a DLL. I do not have control over the tool that will be used to compile - It's going to be the msvc tools invoked via command line.

To that end, I've managed to locate a tutorial on creating DLLs that does not use Visual Studio. it's for mingw, but I've managed to make it work with cl

I've managed to translate part of the process to use with the msvc tools:

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

was translated into

cl /c /D ADD_EXPORTS add.c

I was unable to fully translate the line that follows:

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

But the following worked:

link /DLL /NOENTRY add.obj

and created .exp, .lib, and .dll files. The -s switch doesn't seem important (it strips some info, so I'm guessing at worst I'll get a slightly larger file)

I then managed to create a .obj file from addtest.c, link it (against the .lib file), and got an .exe that runs perfectly fine as long as the dll is keeping it company in the same folder.

On to a harder problem: The library I ultimately want to have compiled after playing around with the #includes and moving some files around to make sure everyone can find their header, I compiled each source file (for windows - to my understanding, _WIN32 is automatically defined when preprocessing) the same way I did add.c (sans ADD_EXPORTS), plus a file of my own, called Source.cpp (I did not create a header for it)

#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;
        }
    }
}

After making a .obj file of them all, I attempted to invoke the linker, with all of the .obj files I've generated, using link /DLL /NOENTRY Source.obj list_ports/list_ports_win.obj win.obj serial.obj

for which I got 134 errors

Information on how to create a DLL without visual studio seems to be quite scarce, and I can't find anything useful about the errors I've looked up (no common mistake I could find when looking up the error + symbol)

What's the problem here?

Edit: Thanks to a comment I managed to find out I have a problem linking to CRT libraries. This helped me cut down on the number of errors, I will see if I can figure anything out about the new output I get and edit further

new linking commands: 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"

Edit 2: compiling the source files with cl /c /clr source_file led to significantly fewer errors when linking without specifying the LIBPATH. I think I might even be able to resolve all those by myself. I will continue to work on this later.

user1999728
  • 913
  • 1
  • 8
  • 25
  • If you are going to use the dll in a native c++ or c in msvc you will want to change `__declspec(dllexport)` to a macro that switches between `__declspec(dllexport)` and `__declspec(dllimport)` depending on if you are building the dll or using it. Also you will need to link to the import library in your application. This Microsoft tutorial covers the details: [https://docs.microsoft.com/en-us/cpp/build/walkthrough-creating-and-using-a-dynamic-link-library-cpp?view=msvc-170](https://docs.microsoft.com/en-us/cpp/build/walkthrough-creating-and-using-a-dynamic-link-library-cpp?view=msvc-170) – drescherjm Apr 13 '22 at 14:47
  • 1
    The other errors seem to be related to the CRT. – drescherjm Apr 13 '22 at 14:50
  • The library you want compiled appears to already support msvc in multiple ways. I would try using CMake but it appears there is also a visual studio project. – drescherjm Apr 13 '22 at 14:52
  • @drescherjm I am not planning to use it in a native C/C++, Unity (game engine, uses C#) offers a way to create an "internal DLL" given a proper source file, so the `import`ing is done in C#. Unfortunately, just providing the code as-is doesn't work, so I'm trying to learn how the whole thing works so I can figure out how to use what little control I have over the compilation process. – user1999728 Apr 13 '22 at 15:04
  • Why do you need to build it? Especially via cmdline (why not using the *.vcxproj* files)? – CristiFati Apr 14 '22 at 12:27
  • @CristiFati I assumed I do based on a comment on another question I've since deleted (because the comment made me think the issue was elsewhere). My problem has been solved (by changing `.cc` file extensions to `.cpp`). but I am still curious and would like a better understanding of how the process works, though considering how little attention the question is getting, looks like I won't get it this time. – user1999728 Apr 14 '22 at 12:47

1 Answers1

1

Note that Serial last official version (v1.2.1) was released in April 2015 (20150422), and the activity has dropped significantly since then.

Please check [SO]: Linking to CRT (unresolved external symbol WinMainCRTStartup) (@CristiFati's answer) (just posted) before going further.

I just built the package and placed the artefacts at [GitHub]: (master) CristiFati/Prebuilt-Binaries - Prebuilt-Binaries/Serial/v024f80634f40073a41be43e956b5ebaca17f6167 (the original code only builds a static library, I enhanced it to also build a dynamic one). Follow the download and "install" instructions.

The attempted scenario is building a .dll from your source code, that uses the downloaded Serial library.

Output:

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

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

[prompt]> dir /b
Source.cpp

[prompt]> set LIBSERIAL_DIR=c:\Program Files\WjwWood\Serial\024f80634f40073a41be43e956b5ebaca17f6167

[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\StackOverflow\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

A "graphical" comparison between the 2 generated .dlls. Notice that the variant linked with libserial.lib requires libserial.dll:

Img0

CristiFati
  • 38,250
  • 9
  • 50
  • 87
  • Incredible! thank you very much. I've gone over it and will do so again later to check out all the flags I don't recognize. – user1999728 Apr 15 '22 at 11:59
  • You're welcome! :) In the *URL*s that I pointed out (I know it's a lot, but I think it's useful) there's a reference to the official documentation about all the flags. – CristiFati Apr 15 '22 at 12:26