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).
Related
I have a project that is compiled into a library and declares a certain function to be implemented by the user of the library:
//To be defined by user
Application* CreateApplication();
When compiling the code into a shared library on Linux this works perfectly. Any user of the library can define an implementation for the declared function and it can be used inside the library. If the user of the library forgets to define an implementation, they will get an error pointing this out.
I'm now in the process of porting the library to Windows, where it is supposed to be compiled into a dll. However, I'm running into problems as the linker used by Visual Studio is complaining:
unresolved external symbol Application* __cdecl CreateApplication(void)
I tried adding the extern keyword to indicate that the definition of the function is somewhere else, but this didn't work.
Why can't I declare (but not define) a function in a dll like this? How should I fix my code so it works both on Linux and on Windows?
What you are attempting to do only works in a static library, it cannot work in a dynamic library like a DLL. For that, you will have to change the code to use a function pointer instead. The application that is using the DLL can pass in the address of the desired function from its own code, and the DLL can then assign that address to a variable that it uses as needed, eg:
HEADER:
#ifndef MYLIB_H
#ifndef MYLIB_H
#ifdef COMPILING_MY_LIB
#define MY_EXPORT __declspec(dllexport)
#else
#define MY_EXPORT __declspec(dllimport)
#endif
// declare Application as needed...
typedef Application (*lpCreateApplicationFunc)();
#ifdef __cplusplus
extern "C" {
#endif
MY_EXPORT void SetCreateApplicationFunc(lpCreateApplicationFunc func);
#ifdef __cplusplus
}
#endif
#endif
DLL:
#define COMPILING_MY_LIB
#include "MyLib.h"
//To be defined by user
lpCreateApplicationFunc CreateApplication = NULL;
void SetCreateApplicationFunc(lpCreateApplicationFunc func)
{
CreateApplication = func;
}
void doSomething()
{
Application *app = NULL;
if (CreateApplication)
app = (*CreateApplication)();
if (app)
{
...
}
}
EXE:
#include "MyLib.h"
Application MyCreateApplicationFunc()
{
...
}
// during startup, call this...
SetCreateApplicationFunc(&MyCreateApplicationFunc);
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.
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.
I am trying to write and test a dll file in C++ that I can call whenever I want filesystem level access to things. I am currently having a huge headache when trying to access the methods in this dll in C++. Strangely enough, I was able to call the code in a separate C# program with little trouble, but I want to get an understanding of how dll interaction works in C++.
And this is the .cpp for my dummy executable that should only call my "newMain" test method.
// dummy.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include <string>
//#pragma comment(lib,"visa32.lib")
#pragma message("automatic link to adsInterface.dll")
#pragma message(lib, "adsInterface.lib"
extern "C" int __stdcall newMain();
int _tmain(int argc, _TCHAR* argv[])
{
newMain();
std::string i;
std::cin >> i
return 0;
}
The problem is, when I run it I get this error:
error LNK2019: unresolved external symbol _newMain#0 referenced in function _wmain
error LNK1120: 1 unresolved externals
Here is the .h for adsInterface:
// adsInterface.h
#ifndef ADSINTERFACE_H
#define ADSINTERFACE_H
/* //save this for later i have no clue how this really works.
#ifdef ADSAPI_EXPORTS
#define ADSAPI __declspec(dllexport)
#else
#define ADSAPI __declspec(dllexport)
#endif
*/
namespace ADSInterface
{
//test method. should print to console.
__declspec(dllexport) int __stdcall newMain();
void hello();
}
#endif
and here is my .cpp for adsInterface:
// adsInterface.cpp : Defines the exported functions for the DLL application.
//
#include "stdafx.h"
#include "adsInterface.h"
#include <iostream>
namespace ADSInterface
{
/* this is where the actual internal class and other methods will go */
void hello()
{
std::cout << "hello from the DLL!" << std::endl;
}
__declspec(dllexport) int __stdcall newMain()
{
hello();
return 0;
}
}
I'll also include the .def file i used when compiling the dll:
; adsInterface.def - defines exports for adsInterface.dll
LIBRARY ADSINTERFACE
;DESCRIPTION 'A C++ dll that allows viewing/editing of alternate data streams'
EXPORTS
newMain #1
Strangely enough, I was able to import the method in C# with this line (I did not have to include a .lib file either):
[DllImport("./adsInterface.dll")] private static extern void newMain();
And it ran when I called it normally:
newMain();
I've been reading many different guides on how to import dll functions, and I've reached the point where I think I'm just mangling together different ways of importation between the languages and just making a mess of things. If anyone is able to provide some insight on how I should be importing dll methods in C++ that would be much appreciated.
delete this declaration:
extern "C" int __stdcall newMain();
and call ADSInterface::newMain() from _tmain.
In the posted code you did not define anything matching that declaration, did you?
Alternatively make the implementation calling the other one, or drag the one from namespace to global.
EDIT
To get around the problem, I added the following to the (beginning of the) header file:
#ifdef GetMessage
#undef GetMessage
static inline BOOL GetMessage(
LPMSG lpMsg,
HWND hWnd,
UINT wMsgFilterMin,
UINT wMsgFilterMax
) {
#if UNICODE
return ::GetMessageW(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax);
#else
return ::GetMessageA(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax);
#endif
}
#endif
I'm creating a C++ DLL (using Visual Studio 2008) from code like the following:
Header File:
#include <windows.h> // Edit: This is the culprit.
class __declspec(dllexport) TestBaseClass
{
protected:
char m_Message[512];
public:
TestBaseClass();
virtual char* GetMessage(void) = 0;
};
class __declspec(dllexport) TestDerivedClass : public TestBaseClass
{
public:
TestDerivedClass();
virtual char* GetMessage(void);
};
CPP File:
TestBaseClass::TestBaseClass()
{
}
TestDerivedClass::TestDerivedClass() : TestBaseClass()
{
}
char* TestDerivedClass::GetMessage(void)
{
sprintf(m_Message, "This is a Message");
return m_Message;
}
When I go to compile the DLL, I get a linker error:
error LNK2001: unresolved external symbol "public: virtual char *
__thiscall TestDerivedClass::GetMessageA(void)" (?GetMessageA#TestDerivedClass##UAEPADXZ)
If I change every instance of "GetMessage" to something else (e.g. "TestFunc"), I do not get the linker error.
Primary Question: Why can't I use "GetMessage" as my function name?
Secondary Question: Is there a way to resolve the linker error, and keep "GetMessage" in my class, as currently defined?
It's due to a quirk in the Windows headers. When you #include <windows.h>, it #defines the symbol GetMessage to either GetMessageA or GetMessageW, depending on whether or not you have Unicode support enabled (more specifically, if the UNICODE macro is defined) -- see Unicode in the Windows API and Conventions for Function Prototypes for more info on that.
To work around this, you have a few options:
Don't include the Windows headers
Define the macro NOMSG before include <windows.h> -- this will suppress the declarations of various message-related functions and macros
#undef GetMessage before your class definition
Rename your function to something else
This is pretty standard preprocessor lossage. Your identifier is getting whacked by a macro. It lives inside the Windows headers, it renames the winapi GetMessage() function to either GetMessageA or GetMessageW, depending on whether UNICODE defined.
Pick another name or use #undef GetMessage