How to create a C++ DLL using another C++ LIB? - c++

I'm trying to generate a DLL based on existing software pieces compiled in a static library (.lib) file. I'm using Visual Studio 2019, and the target is purely Windows.
The existing project (P1) have the following function :
int runLocal();
It's compiled to P1.lib.
In my new DLL project (P2), I have the following code :
#include "..\path\to\P1.h" // declaration of "int runLocal()"
extern "C" __declspec(dllexport) int __stdcall DLLMain() {
int res = runLocal();
std::cout << res << std::endl;
}
Project P2 (DLL) have following linker options :
Additional dependencies: D:\path\to\P1.lib;%(AdditionalDependencies)
However the linker "refuse" to see or use the lib file, and I get this error :
LNK2001 unresolved external symbol "int __stdcall runLocal(void)" (?runLocal##YGHXZ).
In fact, I get excatly the same error if I didn't tell the linker to use P1.lib file.
I have control over all the project sources, so I can change stuffs where it's necessary.
Note 1: The P2 project is used by a debug application (a third project compiled separately) that use LoadLibrary() to run the exported DLLMain function.
Note 2: I already succeeded in compiling an exe file against the same .lib file using the same method. So the difference seems to be in the DLL generation.
Note 3: I tried (without success) to play with many options in Visual project properties, in both compiler & linker section, at least the options that are not beyond my understanding.
So, what should I do to link correctly the .lib file and create my dll ?
Edit 1: I add the compiler & linker options:
P1 compiler options:
/permissive- /GS /TP /GL /analyze- /W3 /Gy /Zc:wchar_t
/I"C:\_tools\boost_1_68_0\" /I"C:\_tools\cryptopp_8_2_0\"
/Qspectre /guard:cf /Zi /Gm- /O2 /sdl /Fd"tmp_Win32_Release\p1.pdb" /Zc:inline
/fp:precise /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_CRT_SECURE_NO_WARNINGS"
/D "_UNICODE" /D "UNICODE" /D "_AFXDLL"
/errorReport:prompt /WX- /Zc:forScope /Gd /Oy /Oi /MD /std:c++17 /FC
/Fa"tmp_Win32_Release\" /EHsc /nologo
/Fo"tmp_Win32_Release\" /Ot /Fp"tmp_Win32_Release\p1.pch" /diagnostics:column
P1 librarian options:
/OUT:"D:\Projets\XL4DLL\Common\p1.lib" /LTCG /MACHINE:X86 /SUBSYSTEM:WINDOWS /NOLOGO
Checked with dumpbin.exe as suggested, and the symbol "?runLocal##YGHXZ" exists in p1.lib
P2 compiler options:
/permissive- /MP /GS /TP /GL /analyze- /W3 /Gy /Zc:wchar_t
/I"C:\_tools\boost_1_68_0\" /I"C:\_tools\cryptopp_8_2_0\"
/Qspectre /guard:cf /Zi /Gm- /O2 /sdl /Fd"tmp_Win32_Release\vc142.pdb"
/Zc:inline /fp:precise /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_USRDLL"
/D "_WINDLL" /D "_UNICODE" /D "UNICODE"
/errorReport:prompt /WX- /Zc:forScope /Gz /Oy /Oi /MD /std:c++17 /FC
/Fa"tmp_Win32_Release\" /EHsc /nologo /Fo"tmp_Win32_Release\" /Ot
/Fp"tmp_Win32_Release\XL4DLL32.pch" /diagnostics:column
P2 linker options:
/OUT:"D:\Projets\XL4DLL\Release\XL4DLL32.dll" /MANIFEST /LTCG:incremental
/NXCOMPAT /PDB:"D:\Projets\XL4DLL\Release\XL4DLL32.pdb" /DYNAMICBASE
"D:\Projets\XL4DLL\Common\p1.lib" "D:\Projets\XL4DLL\Common\SharedToolsLib32.lib"
"kernel32.lib" "user32.lib" "gdi32.lib" "winspool.lib" "comdlg32.lib"
"advapi32.lib" "shell32.lib" "ole32.lib" "oleaut32.lib" "uuid.lib"
"odbc32.lib" "odbccp32.lib"
/IMPLIB:"D:\Projets\XL4DLL\Release\XL4DLL32.lib" /DLL /MACHINE:X86
/OPT:REF /SAFESEH /INCREMENTAL:NO /PGD:"D:\Projets\XL4DLL\Release\XL4DLL32.pgd"
/SUBSYSTEM:WINDOWS /MANIFESTUAC:"level='asInvoker' uiAccess='false'"
/ManifestFile:"tmp_Win32_Release\XL4DLL32.dll.intermediate.manifest"
/OPT:ICF /ERRORREPORT:PROMPT /NOLOGO
/LIBPATH:"C:\_tools\boost_1_68_0\stage\lib" /TLBID:1
There is another difference between P1 and P2 projects configuration:
P1 is configured to use "Use MFC in a Shared DLL"
P2 is configured to use "Use Standard Windows Libraries", because it requires the use of Windows.h header and uses symbols not defined with MFC usage.

Related

Compile using CL.exe with different toolset

I need to compile a program automatically with different platform toolsets. The compilation is done using cl.exe and link.exe like so:
cl.exe file.c /GS- /PlatformToolset=vc140xp /analyze- /W3 /Gy /Zc:wchar_t /Gm- /Od /Zc:inline /fp:precise /D \"WIN32\" /D \"_WINDOWS\" /D \"_UNICODE\" /D \"UNICODE\" /errorReport:prompt /WX- /Zc:forScope /Gd /Oy- /Oi /MD /Fa\"\" /EHsc /nologo /Fo\"\" /Fp\"\" /diagnostics:classic /link %link_additional% /ENTRY:wWinMain /SUBSYSTEM:WINDOWS /MANIFEST:EMBED /NXCOMPAT /DYNAMICBASE \"kernel32.lib\" \"user32.lib\" \"gdi32.lib\" \"winspool.lib\" \"comdlg32.lib\" \"advapi32.lib\" \"shell32.lib\" \"ole32.lib\" \"oleaut32.lib\" \"uuid.lib\" \"odbc32.lib\" \"odbccp32.lib\" /DEBUG:NONE /MACHINE:%arch% /OPT:REF /SAFESEH /INCREMENTAL:NO /SUBSYSTEM:WINDOWS /MANIFESTUAC:\"level = 'asInvoker' uiAccess = 'false'\" /OPT:ICF /ERRORREPORT:PROMPT /NOLOGO /TLBID:1\
I'm using the switch /PlatformToolset=vc140xp but, the cl.exe doesn't seem to reconginze it, i get an error:
Unknown Option: /PlatformToolset
Is there a way you can change toolset using cl.exe, without msbuild and vcproj ?
Just incase someone need it, i was able to solve this isuue. i added this option to cl.exe:
/D \"_USING_V110_SDK71_\"
And also i modified this option:
/SUBSYSTEM:WINDOWS
to
/SUBSYSTEM:WINDOWS,5.01
After the application runs succesfully on windows xp. You might encounter some problems if you are heavily useing crt in your exe, in my exe i only needed CRT to define Tls callbacks, they do not work without CRT, so i guess maybe this is why this worked for me

VS 2013 release DLL linking to debug version

I have the following (example) code of which I require to compile a release version.
// library.cpp : Defines the exported functions for the DLL application.
//
#include <stdio.h>
extern "C"
{
__declspec(dllexport) void DisplayHelloFromDLL( int value)
{
printf("Hello from DLL : data=%d\n", value);
}
}
The code compiles and links with one problem that it refers to the debug version of the
runtime library no matter what I try.
Platform Visual Studio 2013 update 5
Issues - Links to MSVCR120d.dll as opposed to MSVCR120.dll
Configuration Release - Win32 Dll
Manifest Present
Compiler CLI
/GS /GL /analyze- /W3 /Gy /Zc:wchar_t /Zi /Gm- /O2 /Fd"Release\vc120.pdb" /fp:precise /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_USRDLL" /D "LIBRARY_EXPORTS" /D "_WINDLL" /D "_UNICODE" /D "UNICODE" /errorReport:prompt /WX- /Zc:forScope /Gd /Oy- /Oi /MD /Fa"Release\" /EHsc /nologo /Fo"Release\" /Fp"Release\library.pch"
Note: /MD is correct i.e. no static, no debug, dll
Linker CLI
/OUT:"C:_progdbg\Call_DLL\Caller\Release\library.dll" /MANIFEST /LTCG /NXCOMPAT /PDB:"C:_progdbg\Call_DLL\Caller\Release\library.pdb" /DYNAMICBASE "kernel32.lib" "user32.lib" "gdi32.lib" "winspool.lib" "comdlg32.lib" "advapi32.lib" "shell32.lib" "ole32.lib" "oleaut32.lib" "uuid.lib" "odbc32.lib" "odbccp32.lib" /IMPLIB:"C:_progdbg\Call_DLL\Caller\Release\library.lib" /DLL /MACHINE:X86 /OPT:REF /SAFESEH /INCREMENTAL:NO /PGD:"C:_progdbg\Call_DLL\Caller\Release\library.pgd" /SUBSYSTEM:WINDOWS /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /ManifestFile:"Release \library.dll.intermediate.manifest" /OPT:ICF /ERRORREPORT:PROMPT /NOLOGO /TLBID:1
Dependency Walker shows that library is dependent on MSVCR120d.dll
Could someone please tell me which setting is wrong.
Many Thanks

C++ DLL not loading debug symbols

In my solution I have two projects: one is a C++ DLL, and the other is a C# Windows Forms EXE (with the latter having a build dependency on the former). The DLL gets linked in correctly and works (my test function returns the right number, at least). The actually useful functionality is throwing an exception somewhere, but I can't debug it because none of the debug symbols for the C++ project are being loaded.
The PDB is definitely being generated! The EXE, DLL and PDB are all in the same folder. I even added their directory as one of the symbol file locations (Options > Debugging > Symbols), but this didn't do anything.
Apparently, the Modules window is supposed to tell you something, but my DLL doesn't appear there (yet it still works fine).
I'm using a x64 DLL with no compiled headers, if that makes any difference.
Compiler commandline:
/GS /W3 /Zc:wchar_t /I"E:\Users\Sean\Documents\Visual Studio 2015\Projects\MusicStreamingClient\MusicStreamingClient\RapidJson\include\" /ZI /Gm /Od /Fd"x64\Debug\vc140.pdb" /Zc:inline /fp:precise /D "_DEBUG" /D "_WINDOWS" /D "_USRDLL" /D "MUSICSTREAMINGCLIENT_EXPORTS" /D "_WINDLL" /D "_UNICODE" /D "UNICODE" /errorReport:prompt /WX- /Zc:forScope /RTC1 /Gd /MDd /Fa"x64\Debug\" /EHsc /nologo /Fo"x64\Debug\" /Fp"x64\Debug\MusicStreamingClient.pch"
Linker commandline:
/OUT:"E:\Users\Sean\Documents\Visual Studio 2015\Projects\MusicStreamingClient\x64\Debug\MusicStreamingClient.dll" /MANIFEST /NXCOMPAT /PDB:"E:\Users\Sean\Documents\Visual Studio 2015\Projects\MusicStreamingClient\x64\Debug\MusicStreamingClient.pdb" /DYNAMICBASE "E:\Users\Sean\Documents\Visual Studio 2015\Projects\MusicStreamingClient\MusicStreamingClient\RapidJson\x64\Debug\RapidJson.lib" "kernel32.lib" "user32.lib" "gdi32.lib" "winspool.lib" "comdlg32.lib" "advapi32.lib" "shell32.lib" "ole32.lib" "oleaut32.lib" "uuid.lib" "odbc32.lib" "odbccp32.lib" /IMPLIB:"E:\Users\Sean\Documents\Visual Studio 2015\Projects\MusicStreamingClient\x64\Debug\MusicStreamingClient.lib" /DLL /MACHINE:X64 /INCREMENTAL /PGD:"E:\Users\Sean\Documents\Visual Studio 2015\Projects\MusicStreamingClient\x64\Debug\MusicStreamingClient.pgd" /SUBSYSTEM:WINDOWS /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /ManifestFile:"x64\Debug\MusicStreamingClient.dll.intermediate.manifest" /ERRORREPORT:PROMPT /NOLOGO /TLBID:1
Any help would be appreciated.
You are currently debugging Managed code only. Native symbols will not be visible. You need to change your debug option to enable both Managed and Native modes for your project.

Is it possible to statically link libcurl, libeay32 and ssleay32?

I'm using Visual Studio 2013 and I want to use libcurl statically (without any external dlls).
I've statically linked libcurl that I've compiled with the following command:
nmake /f Makefile.vc mode=static WITH_SSL=static WITH_DEVEL=C:\OpenSSL-Win32 VC=12 ENABLE_SSPI=no ENABLE_IDN=no ENABLE_WINSSL=no DEBUG=no MACHINE=x86 GEN_PDB=no ENABLE_IPV6=yes
I have downloaded OpenSSL and linked the following libs to my project:
C:\OpenSSL-Win32\lib\VC\static\zlibeay32MD.lib
C:\OpenSSL-Win32\lib\VC\static\ssleay32MD.lib
Everything seems to be fine, and I can successfully compile my project.
But when I run the program, I'm receiving the following error:
If I put libeay32.dll and ssleay32.dll to the same folder of program it works without problem.
I don't understand why it requires these dlls, I've used WITH_SSL=static option to compile libcurl and should load from static library, right?
Update:
C/C++ -> Command Line:
/Yu"stdafx.h" /GS /GL /analyze- /W3 /Gy /Zc:wchar_t /I"C:\VisualCpp\Libraries\curl-7.42.1\builds\libcurl-vc12-x86-release-static-ssl-static-ipv6\include\curl" /I"C:\OpenSSL-Win32\\include\openssl" /Zi /Gm- /O2 /sdl /Fd"Release\vc120.pdb" /fp:precise /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "CURL_STATICLIB" /D "_UNICODE" /D "UNICODE" /errorReport:prompt /WX- /Zc:forScope /Gd /Oy- /Oi /MD /Fa"Release\" /EHsc /nologo /Fo"Release\" /Fp"Release\Launcher.pch"
Linker -> Command Line:
/OUT:"C:\VisualCpp\Launcher\Release\Launcher.exe" /MANIFEST /LTCG /NXCOMPAT /PDB:"C:\VisualCpp\Launcher\Release\Launcher.pdb" /DYNAMICBASE "libcurl_a.lib" "libeay32MD.lib" "ssleay32MD.lib" "ws2_32.lib" "wldap32.lib" "advapi32.lib" "kernel32.lib" "comdlg32.lib" "user32.lib" "gdi32.lib" "winspool.lib" "shell32.lib" "ole32.lib" "oleaut32.lib" "uuid.lib" "odbc32.lib" "odbccp32.lib" /MACHINE:X86 /NODEFAULTLIB:"libcmt.lib" /OPT:REF /SAFESEH /INCREMENTAL:NO /PGD:"C:\VisualCpp\Launcher\Release\Launcher.pgd" /SUBSYSTEM:WINDOWS /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /ManifestFile:"Release\Launcher.exe.intermediate.manifest" /OPT:ICF /ERRORREPORT:PROMPT /NOLOGO /TLBID:1

Dll compiled under Windows 7 doesn't work in Windows XP

I'm building an addon for NodeJS.
Works just right in Windows 7. But in Windows XP it won't load, doesn't open it no matter what I do. ERROR: Unable to load shared library c:\tst\tst.node
I'm compiling the DLL from VS2010 with the following options:
c/c++ opts
/I"c:\tst\nodemodule\cvv8\include" /I"c:\tst\nodemodule\node-src\deps\uv\include" /I"c:\tst\nodemodule\node-src\deps\v8\include" /I"c:\tst\nodemodule\node-src\src" /I"c:\tst\nodemodule\node-src\deps\zlib" /I"c:\tst\nodemodule\node-src\deps\http_parser" /I"c:\tst\nodemodule\cvv8\include\cvv8" /Zi /nologo /W0 /WX- /O2 /Oi /Oy- /GL /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_USRDLL" /D "TST_EXPORTS" /D "_WINDLL" /D "_UNICODE" /D "UNICODE" /Gm- /EHsc /GS /Gy /fp:precise /Zc:wchar_t /Zc:forScope /Fp"Release\tst.pch" /Fa"Release\" /Fo"Release\" /Fd"Release\vc100.pdb" /Gd /analyze- /errorReport:queue
linker opts
/OUT:"c:\tst\tst.node" /INCREMENTAL:NO /NOLOGO /DLL "kernel32.lib" "user32.lib" "gdi32.lib" "winspool.lib" "comdlg32.lib" "advapi32.lib" "shell32.lib" "ole32.lib" "oleaut32.lib" "uuid.lib" "odbc32.lib" "odbccp32.lib" /MANIFEST:NO /ManifestFile:"Release\tst.node.intermediate.manifest" /ALLOWISOLATION /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /PDB:"c:\tst\tst.pdb" /SUBSYSTEM:WINDOWS /OPT:REF /OPT:ICF /PGD:"c:\tst\tst.pgd" /LTCG /TLBID:1 /DYNAMICBASE /NXCOMPAT /MACHINE:X86 /ERRORREPORT:QUEUE
What's wrong? Is this UTF-8 related?
The best tool to diagnose such problems is the dependency walker.
Open your dll in dw and you'll immediately see why it won't load: most likely there are some dlls/libs missing your dll depends upon.
Before including windows headers (usually in stdafx.h), try setting the windows version macros to ensure you're not using api's that are only available after XP.
http://msdn.microsoft.com/en-us/library/windows/desktop/aa383745(v=vs.85).aspx#setting_winver_or__win32_winnt