How to export class constructor in c++ DLL project? - c++

I'm building a dll project in Visual Studio 2013. My header file for class definition is as follows:
#ifndef PREPROCESSOR_H
#define PREPROCESSOR_H
#ifndef MAKEDLL
#define DLLEXPORT __declspec(dllexport)
#else
#define DLLEXPORT __declspec(dllimport)
#endif
#include "common.h"
class DLLEXPORT Preprocessor
{
public:
Preprocessor();
...
private:
...
};
After building it, I called this class from another project. I've included its header file, generated dll and .lib files. But I got a LNK2001 error for my main.obj file:
error LNK2001: unresolved external symbol "public: __cdecl Preprocessor::Preprocessor (void)" (??0Preprocessor##QEAA#XZ
What did I wrong here?? Thank you.

Related

VC++ linker error when using dllimport/dllexport macro to include headers in multiple projects

I have a Visual C++ solution, using Visual Studio 2017, which contains 5 projects:
SpikeConfig
SpikeEngine
SpikeRenderer
SpikeUI
SpikeUtils
In SpikeUtils, I have a header _SpikeEngineObject.h:
#pragma once
#ifdef DLL_SPIKEUTILS
#define SPIKEUTILS_EXPORT __declspec(dllexport)
#else
#define SPIKEUTILS_EXPORT __declspec(dllimport)
#endif
#include "GUID.h"
namespace SpikeUtils
{
class SPIKEUTILS_EXPORT _SpikeEngineObject
{
public:
const std::string & _SpikeEngineId()
{
return _SpikeRef.Value();
}
private:
SpikeUtils::GUID _SpikeRef = SpikeUtils::GUID::Generate();
};
}
The file GUID.h included looks like this:
#pragma once
#include <iostream>
#ifdef DLL_SPIKEUTILS
#define SPIKEUTILS_EXPORT __declspec(dllexport)
#else
#define SPIKEUTILS_EXPORT __declspec(dllimport)
#endif
namespace SpikeUtils
{
class SPIKEUTILS_EXPORT GUID final
{
public:
GUID(GUID const & other) = default;
GUID& operator=(GUID& other) = default;
static GUID Generate();
std::string const & Value();
private:
GUID(std::string const & value) : value(value)
{}
std::string value;
};
}
I am omitting the implementation of GUID.cpp because I don't think it's relevant.
Now, in SpikeUI, I have a class Drawable, that just inherits from _SpikeEngineObject.h
#pragma once
#include "_SpikeEngineObject.h"
#ifdef DLL_SPIKEUI
#define SPIKEUI_EXPORT __declspec(dllexport)
#else
#define SPIKEUI_EXPORT __declspec(dllimport)
#endif
namespace SpikeUI
{
namespace UI
{
struct SPIKEUI_EXPORT Drawable : SpikeUtils::_SpikeEngineObject
{
....
};
}
}
Obviously, all the respective DLL_ defines have been put inside each individual project's C/C++ -> Preprocessor -> Preprocessor definitions, so the projects should build with the appropriate dllimport / dllexport macro.
But when I try and build SpikeUI, I get linker errors like:
LNK2019 unresolved external symbol "__declspec(dllimport) public: __cdecl
SpikeUtils::_SpikeEngineObject::_SpikeEngineObject(void)" (__imp_??
0_SpikeEngineObject#SpikeUtils##QEAA#XZ) referenced in function "public:
__cdecl SpikeUI::UI::Drawable::Drawable(enum SpikeUI::UI::DrawableType)" (??
0Drawable#UI#SpikeUI##QEAA#W4DrawableType#12##Z)
and
LNK2019 unresolved external symbol "__declspec(dllimport) public: __cdecl
SpikeUtils::_SpikeEngineObject::~_SpikeEngineObject(void)" (__imp_??
1_SpikeEngineObject#SpikeUtils##QEAA#XZ) referenced in function "int
`public: __cdecl SpikeUI::UI::Drawable::Drawable(struct UI::Drawable::dtor$0
const &)'::`1'::dtor$0" (?dtor$0#?0???0Drawable#UI#SpikeUI##QEAA#AEBU012##Z#4HA)
An interesting fact is that Visual Studio even highlights which macro will be used, and for example GUID.h does highlight the dllexport macro, but _SpikeEngineObject.h highlights the dllimport macro for some reason.
Searching through SO and MSDN, it looks like this macro pattern should work, but for some reason it's not consistent on my project.
How can I solve the linker errors?
Answering my own question here:
The SpikeUI project has a dependency on the SpikeUtils project, and it is linked against the .lib and .dll project that is outputed by building the SpikeUtils project.
Now, the problem was that the class _SpikeEngineObject was a header-only class (ie no .cpp for the class). Hence, I am assuming that the SpikeUtils.lib did not contain any symbols for the constructor / destructor etc. of the _SpikeEngineObject, so the linker was having problems linking it.
I solved the problem by adding a .cpp file for the class and implementing dumb constructor / destructor so that the compiler would generate these symbols, and everything was fine.

complie dll but appear error LNK2019

I implement a C++ function as DLL with vs2013. But I have linker error (error LNK2019: unresolved external symbol _main referenced in function ___tmainCRTStartup) building to the dll. I have proper setup and not sure what is wrong. The code is very simple, but I don't know why it can't be built successfully.
Demoone.h
#ifndef _Demo_H_
#define _Demo_H_
#ifdef LIBDLL
#define LIBDLL extern "C" _declspec(dllimport)
#else
#define LIBDLL extern "C" _declspec(dllexport)
#endif
LIBDLL int Add(int plus1, int plus2);
#endif
Demoone.cpp
#include "Demoone.h"
int Add(int a, int b)
{
return (a + b);
}
update:
I modified the header file as bellow
#ifndef _Demo_H_
#define _Demo_H_
extern "C" int Add (int a , int b);
#endif
and add an def file
LIBRARY "Dllmaketwo"
EXPORTS
Add # 1
The same linker error (error LNK2019: unresolved external symbol _main referenced in function ___tmainCRTStartup) also appeared.
If you want to use load-time linking in the project that uses the DLL you need to link against the .lib produced by the DLL project build.
You can do that with:
#pragma comment(lib, "dllproject.lib")
Or by adding the .lib to the additional dependencies line in the project settings under Linker->Input. You may also need to mess with the library search path, either in the VC++ Directories page or in the Linker->General page.
#ifndef _Demo_H_
#define _Demo_H_
#ifdef LIBDLLIMPORT //Changed here
#define LIBDLL extern "C" _declspec(dllimport)
#else
#define LIBDLL extern "C" _declspec(dllexport)
#endif
LIBDLL int Add(int plus1, int plus2);
#endif
You should not use a same name in #ifdef and #define,
Did you setup you project correctly? And you should not write a `main()' function in it.

error resolving external symbol

I am trying to create a simple c++ project in Visual studio 2015
Peakdetector.h
#ifndef PEAKDETECTOR_H
#define PEAKDETECTOR_H
//-------------------------------------------------------
#ifdef DLL_BUILD_SETUP
#ifdef Q_OS_LINUX
#define DLLSPEC __attribute__((visibility("default")))
#else
#define DLLSPEC __declspec(dllexport)
#endif
#else
#ifdef Q_OS_LINUX
#define DLLSPEC
#else
#define DLLSPEC __declspec(dllimport)
#endif
#endif
namespace vpg {
#ifndef VPG_BUILD_FROM_SOURCE
class DLLSPEC PeakDetector
#else
class PeakDetector
#endif
private:
int __seek(int d) const;
double __getDuration(int start, int stop);
}
inline int PeakDetector::__seek(int d) const
{
return ((m_intervalslength + (d % m_intervalslength)) % m_intervalslength);
}
#endif
PeakDetector.cpp
#include "stdafx.h"
#include "peakdetector.h"
namespace vpg {
void PeakDetector::__updateInterval(double _duration)
{
//other stuff
}
}
When I try to run this application i get error
LNK2019 unresolved external symbol "__declspec(dllimport) private: int __cdecl vpg::PeakDetector::__seek(int)const " (__imp_?__seek#PeakDetector#vpg##AEBAHH#Z) referenced in function "private: void __cdecl vpg::PeakDetector::__updateInterval(double)" (?__updateInterval#PeakDetector#vpg##AEAAXN#Z) MyCustomProject
I am new to this and cannot figure out why am I having this error.I have just copy pasted this code from an example.Please let me know if I am missing any code. Also I dont have any .lib files.
You must add the DLL_BUILD_SETUP the defines in Visual Studio.
In order to do that, yo must go to
Project Settings -> C/C++ -> Preprocessor -> Preprocessor definitions
and add the definition to the list.
You must use the spec __declspec(dllexport) when compiling the library that is exporting the symbols (in this case the class), and __declspec(dllimport) in the project that USES that library.
I see from the source code that you've provided that there is an additional definition VPG_BUILD_FROM_SOURCE which disables the export in order to using static/inline linking, you may try to add that define instead.

LNK2019 unresolved external appears when function is used inside static method

I have a C++ Visual Studio 2013 console application which is supposed to make use of a DLL MyDLLlib.dll which I have written. MyDLLlib is written in C. One of the functions is called Get_Version. The prototype is
const char *Get_Version();
I put this at the top of the source files to make use of the prototype:
extern "C"{
#include "MyDLLlib.h"
}
If in the function is called in the main as this
printf("version %s\n",Get_Version());
then it works.
However if I add a class with some static methods and a static method makes a call to Get_Version()
const char * ret = Get_Version();
then I get a link error:
Error 1 error LNK2019: unresolved external symbol
"__declspec(dllimport) char * __cdecl Get_Version(void)" (__imp_?Get_Version##YAPADXZ)
referenced in function "private: static class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __cdecl ServiceDispatch::decoder_Get_Version(class StringBuffer &)"
(?decoder_Get_Version#ServiceDispatch##CA?AV?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std##AAVStringBuffer###Z)
D:\devt\CplusPlus\VSTrials\Link_to_MyDLLlib\Link_to_MyDllLib\ServiceDispatch.obj Link_to_MyDLLlib``
I am using the same include.
Any clue as to what I might be doing wrong?
If you have CLASS_DECLSPEC defined always as __declspec(dllimport), this will not work for sure. Look at this sample:
DLL_header.h
#if defined( _BUILD_DLL )
# define DLLAPI __declspec(dllexport) //Export when building DLL
#else
# define DLLAPI __declspec(dllimport) //Import when using in other project
#endif
DLLAPI const char *Get_Version();
DLL_source.cpp
#include "Header.h"
const char *Get_Version()
{
return "1.1.0.4";
}
Build DLL with _BUILD_DLL defined.
Main.cpp
#include "DLL_header.h"
int main()
{
printf("%s\n", Get_Version());
return 0;
}
Build this, with _BUILD_DLL not defined.
In your case, it could be problem with extern "C" - you include header inside extern "C", which declares Get_Version() as having __cdecl linkage. But linker is searching for
__imp_?Get_Version##YAPADXZ
Which is a mangled (C++) name. Is your DLL a C or C++ project? If your DLL is build as C project (not C++), put extern "C" on Get_Version()'s declaration with this #ifdef:
#ifdef __cplusplus
extern "C" {
#endif
DLLAPI const char *Get_Version();
#ifdef __cplusplus
}
#endif
Either way, remove extern "C" from around the #include. Also, check if .lib file for this DLL is attached to project as dependency.

error LNK2001: unresolved external symbol with DLL

I created a DLL project and successfully built it. I then tried to use the DLL in another Project, TEST, and I am getting the following error.
Error 1 error LNK2001: unresolved external symbol "public: void __thiscall SnoMessage::setRawMessageName(class ATL::CStringT<wchar_t,class StrTraitMFC_DLL<wchar_t,class ATL::ChTraitsCRT<wchar_t> > >)" (?setRawMessageName#SnoMessage##QAEXV?$CStringT#_WV?$StrTraitMFC_DLL#_WV?$ChTraitsCRT#_W#ATL#####ATL###Z)
I added the required lib in the linker properties, and I also added the header files in the TEST include directory. So the function is being recognized, but it keeps giving those errors. The DLL is comprised of the following files
SnoMessage.h
#pragma once
#include "StdAfx.h"
class SnoMessage
{
public:
__declspec(dllexport) SnoMessage(void);
__declspec(dllexport) ~SnoMessage(void);
__declspec(dllexport) void setRawMessageName(CString messageName);
__declspec(dllexport) void setRawMessageType(CString messageType);
__declspec(dllexport) void setRawMessageAttributes(std::map<CString,CString> attributes);
__declspec(dllexport) CString getRawMessageName();
__declspec(dllexport) CString getRawMessageType();
__declspec(dllexport) std::map<CString,CString> getRawMessageAttributes();
private:
CString messageName;
CString messageType;
std::map<CString,CString> attributes;
};
SnoMessage.cpp
#include "stdafx.h"
#include "SnoMessage.h"
SnoMessage::SnoMessage(void)
{
}
SnoMessage::~SnoMessage(void)
{
}
void SnoMessage::setRawMessageName(CString messageName){
this->messageName = messageName;
}
void SnoMessage::setRawMessageType(CString messageType){
this->messageType = messageType;
}
void SnoMessage::setRawMessageAttributes(std::map<CString,CString> attributes){
this->attributes = attributes;
}
CString SnoMessage::getRawMessageName(){
return messageName;
}
CString SnoMessage::getRawMessageType(){
return messageType;
}
std::map<CString,CString> SnoMessage::getRawMessageAttributes(){
return attributes;
}
And in test I am doing the following:
test.cpp
// test.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "SnoMessage.h"
int _tmain(int argc, _TCHAR* argv[])
{
SnoMessage *msg = new SnoMessage();
msg->setRawMessageName("TEST");
return 0;
}
Let me know if you need more info, thanks.
In your dll define this in some header you want to use for your export defs...
MyExports.h
#ifdef SNOMESSAGE_EXPORTS
#define SNOMESSAGE_API __declspec(dllexport)
#else
#define SNOMESSAGE_API __declspec(dllimport)
#endif
Now in your dll you just define SNOMESSAGE_EXPORTS, then when your dll is compiled your class and methods will be visible to the exe. But when you include those same headers in the exe the Macro will import them instead of export.
//In the DLL this is == to export, in the executable this is import. Problem solved.
class SNOMESSAGE_API SnoMessage
{
public:
//...
};
You no longer need to export each member, just the class.
I would mark the whole class as exported, not just its member functions. Also, following the advice of this conversation, you need to specify __declspec(dllecport) or __declspec(dllimport) based on whether you are including the header in the DLL or the code that uses the DLL; and define the guarding macro in the DLL project.
When you compile the DLL you should have __declspec(dllexport), but when you compile exe you should have __declspec(dllimport). The easiest way to do this is to have a #define somewhere that has different value when "in DLL" and "out of DLL". Also do export the whole class instead of individual methods.
There is a case when dll compile use C call but exe use standard call, the link in x64 has no problem, but when using win32 will show this link error 2001. For that situation just use C call for both dll and exe for win32 platform (https://learn.microsoft.com/en-us/cpp/error-messages/tool-errors/name-decoration?view=msvc-160).