I have a DLL with the /clr option ON. I have the following declaration in my DLL:
int __declspec(dllexport) __cdecl test();
Also, I have a console with /clr option ON. And have the following declaration on my main.cpp file:
int __declspec(dllimport) __cdecl test();
I added the Reference to the DLL project on the property settings of my console application. But I still get unresolved externals from the compiler about the test function.
I managed to compile by manually adding a reference to the lib file generated by the compiler. But then I can't hit breakpoints inside the DLL functions (it says the source code is different from the original version or the symbols have not been loaded...)
Can someone help me?
If your DLL doesn't use any managed functionality, simply remove the /clr option from that project and recompile. If you still get the errors, it's probably related to the references in the console application.
If the DLL use managed functionality, what you need is instead like so:
DLL:
#include "stdafx.h"
namespace Test1
{
public ref class Test2
{
public:
static int test()
{
return 1;
}
};
}
Console app:
#include <iostream>
int main(int argc, char* argv[])
{
int i = Test1::Test2::test();
std::cout << i << std::endl;
return 0;
}
Related
I'm new to codelite and c++. I'm using Linux and the g++ compiler. I've set up a simple project with two source files just to play around with linker errors. The files look like so:
Main.cpp:
#include <iostream>
void Log(const char*);
static int Multiply (int a, int b)
{
Log("Multiply");
return a * b;
}
int main()
{
std::cout << Multiply(5, 8) << std::endl;
std::cin.get();
}
Log.cpp:
#include <iostream>
void Log(const char* message)
{
std::cout << message << std::endl;
}
As you can see, Log.cpp simply specifies a function called in main. Both files are in the same directory, "src". So far all my settings are pretty much default, still I get an "undefined reference to `Log(..." error when I try to build this project.
Also, if I comment out the declaration of the Log function at the top of main.cpp, I would expect a compilation error since an undeclared function being called. Yet if I try to compile main.cpp I get no errors.
This is what my workspace looks like
Project settings
Compiler settings
Linker settings
Am I correct to expect the behaviors described above? Is there some setting I have to manually configure?
I am working in Visual Studio C++.
I made an class with a non-static function and packaged it as a dll. Here is the code to generate my dll:
// head file
#ifndef FUNCTIONS_H_
#define FUNCTIONS_H_
#include <string>
#include <memory>
#ifdef MATHFUNCSDLL_EXPORTS
#define MATHFUNCSDLL_API __declspec(dllexport)
#else
#define MATHFUNCSDLL_API __declspec(dllimport)
#endif
MATHFUNCSDLL_API class Functions
{
public:
MATHFUNCSDLL_API void func(int, std::string);
};
extern "C" MATHFUNCSDLL_API Functions * __cdecl create_class();
#endif
// cpp file
#include "stdafx.h"
#include "Functions.h"
#include <iostream>
void Functions::func(int id, std::string name)
{
std::cout << "Your ID: " << id << ". Your name: " << name << std::endl;
}
Functions * create_class()
{
std::cout << __FUNCTION__ << std::endl;
return new Functions();
}
Now I have a C++ project that loads this dll dynamically. Here is the code:
#include <iostream>
#include <Windows.h>
#include "../../testDmcDLL/testDmcDLL/Functions.h"
typedef Functions *(__stdcall *f_funci)();
int main(int argc, char ** argv)
{
HINSTANCE hGetProcIDDLL = LoadLibrary("C:\\Documents\\Visual Studio 2013\\Projects\\testDmcDLL\\Debug\\testDmcDLL.dll");
f_funci func_create_class = (f_funci)GetProcAddress(hGetProcIDDLL, "create_class");
Functions * pf = func_create_class();
////LNK error////pf->func(1, "toto");
system("pause");
return 0;
}
I can make sure that hGetProcIDDLL and func_create_class have been initialized successfully (I've tested them with if, but here I removed the if).
When I run this project, I can see that create_class is shown on the console because there is std::cout << __FUNCTION__ << std::endl; in that function. So everything looks fine.
However, when I compile it with the code pf->func(1, "toto") uncommented, I get a linker (LNK2019) error:
Error 1 error LNK2019: unresolved external symbol
"__declspec(dllimport) public: void __thiscall
Functions::func(int,class std::basic_string,class std::allocator >)"
(__imp_?func#Functions##QAEXHV?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std###Z)
referenced in function _main c:\documents\visual studio
2013\Projects\testLoadDmcDLL\testLoadDmcDLL\main.obj testLoadDmcDLL
The class definition is not quite right with the exports, it should be of the form;
class MATHFUNCSDLL_API Functions // MATHFUNCSDLL_API moved
{
public:
void func(int, std::string); // MATHFUNCSDLL_API removed
};
Once a class is exported, all its members are exported.
You don't mention how MATHFUNCSDLL_EXPORTS is defined during compilation (from the command line or possibly in the stdafx.h), but make sure it is defined when building the dll, but not when building the exe. Be sure to link against the .lib produced with the .dll.
Notes on the LoadLibrary and GetProcAddress usage; if you require the dll to be loaded dynamically, you need to get the C++ class member function bound to the exported function. I've not seen a successful implementation of this or if it is even reasonable possible. If the use of the LoadLibrary and GetProcAddress is required, consider using an abstract class and create the object in a factory of some sort.
You don't detail the motivation for the dynamic loading of the dll, but consideration could also be given the delay loading the dll.
If the motivation is to delay the loading of the dll, but the same dll is always used, then the delay-load linking may help. If the motivation is to load an unknown dll (by name/location) based on some runtime parameter (or configuration), then the virtual base class and a single C-style function as a factory for the object is probably the preferred solution.
There is a good code project article on this describing various solutions for this. In particular using the abstract base class is very portable.
If you don't rely on the import library but call GetProcAddress, you need to do that for every function you're importing. You never called GetProcAddress for __imp_?func#Functions##QAEXHV?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std###Z (which is how your Functions::func is mangled in the DLL).
Also, be aware that you get a function pointer from GetProcAddress. While that points to the code implementing pf->func, function pointers aren't called with member function call syntax.
The root problem is that GetProcAddress really is designed for C, not C++.
Here is the error I am receiving when running the project that I am using the DLL in:
The odd thing is that this was working at one point. I took a break from this project for a while and now it is not working. Not much has changed besides changing a couple of the parameters.
My setup includes a project in which I build the DLL. This project is then used in a solution with another project that I use to test it. I followed this example: https://msdn.microsoft.com/en-us/library/ms235636.aspx in which I also followed the first time and had it working, now it has stopped.
After realizing it seems to be only one of the functions that is causing the problem I have removed all of the extra code, tried renaming the function, removing everything in it and it is STILL not working.
You can see the function definitions and signatures to see how I am attempting to get this to work below
I have also tried using the "SCOREINTERFACECPP" macro I created on the function instead of the class and I get the same error.
In the project I am testing it in I added the DLL project as a reference and a dependent project, then imported the header file. The other functions I have in the dll (that I have removed from this code for simplicity sake) seem to be working.
Header:
#ifdef SCOREINTERFACECPP_EXPORTS
#define SCOREINTERFACECPP __declspec(dllexport)
#else
#define SCOREINTERFACECPP __declspec(dllimport)
#endif
#include <time.h>
#include <queue>
namespace ScoreInterfaceCPP
{
class SCOREINTERFACECPP ScoreInterface
{
public:
ScoreInterface();
~ScoreInterface();
static void SubmitLogin(const std::string &displayName, const std::string &password);
static void Shutdown();
static SIEvent* GetNextEvent();
static void ClearEvents();
static int GetEventCount();
private:
static std::queue< SIEvent* > mSIEvents;
static bool mGameIsAuthorized;
static std::string mGameName;
static std::string hexedKey;
static std::wstring mAddress;
static void SubmitEventString(std::string eventString);
static int SubmitWithNewThread(void* data);
static void PostMessage(std::string data, std::string iv);
};
}
Source:
#include <sstream>
#include <SDL/SDL_thread.h>
#include <boost/tokenizer.hpp>
#include "ScoreInterfaceCPP.h"
#include "Network.h"
using namespace ScoreInterfaceCPP;
/*
ScoreInterfaceCPP.h
Handles the sending and receiving of events.
*/
ScoreInterface::ScoreInterface()
{
}
ScoreInterface::~ScoreInterface()
{
}
void ScoreInterface::SubmitLogin(const std::string &displayName, const std::string &password)
{
}
void ScoreInterface::SubmitEventString(std::string eventString)
{
}
int ScoreInterface::SubmitWithNewThread(void* data)
{
return 0;
}
SIEvent* ScoreInterface::GetNextEvent()
{
return NULL;
}
int ScoreInterface::GetEventCount()
{
return 0;
}
void ScoreInterface::ClearEvents()
{
}
void ScoreInterface::Shutdown()
{
}
Test file:
#include "ScoreInterfaceCPP.h"
using namespace ScoreInterfaceCPP;
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
ScoreInterface si = ScoreInterface();
si.SubmitLogin("noplayer", "nopassword");
return 0;
}
In my experience, usually problems of this type come with two things you should check (assuming the DLL was built successfully):
Check that the DLL being loaded at runtime is the correct version.
Ensure that the function in question is actually exported.
For the first issue, you can use a utility such as Process Explorer and look at the DLL handles that are loaded for your running exectuable. If you are using Visual C++, you can also look at the Output Window listing of the DLL's that are loaded, and ensure that the version you're using is being loaded.
Many times during development, you may have several (either by accident or by design) versions of your DLL lying in a directory that is accessible by Windows (see DLL Search Order), and thus an old or different version of your DLL is being loaded when you run your application.
For the second issue, there is dumpbin.exe, but I find the Dependency Walker a little more friendly to use. These utilities will show you the functions that are exported from the DLL.
If it is discovered that the function was not exported, then you need to rebuild your DLL, ensuring that __declspec(dllexport) has been used on the function or class you're exporting.
I am trying to compile a very simple CMake project using Visual Studio 2013, however I am getting the following error upon trying to compile it:
error LNK1120: 1 unresolved externals cmake_issue\build\Debug\cmake_issue.exe 1 1 cmake_issue
error LNK2001: unresolved external symbol "public: static int Other::value" (?value#Other##2HA) cmake_issue\build\test.obj cmake_issue
I have a base directory with the following CMakeLists.txt in:
project(cmake_issue)
add_subdirectory(other)
add_executable(cmake_issue src/test.cc)
target_link_libraries(cmake_issue other)
And the contents of src/test.cc:
#include <cstdio>
#include "other/other.h"
int main(int argc, char *argv[]) {
printf("value = %d\n", Other::value);
return 0;
}
And a subdirectory called other with the following CMakeLists.txt in:
add_library(other SHARED src/other.cc)
target_include_directories(other PUBLIC include)
target_link_libraries(other)
And the contents of other/include/other/other.h:
#ifndef _OTHER_H_
#define _OTHER_H_
class __declspec(dllexport) Other {
public:
static int value;
};
#endif
And the contents of other/src/other.cc:
#include "other/other.h"
int Other::value = 30;
If I build the project with cmake and then open the generated sln in Visual Studio, both of the projects appear in the Solution Explorer.
If I right click and build other, it builds fine. However if I try and build cmake_issue, I get the errors above. It looks like the cmake_issue solution is not using the other.dll (or other.lib) files being generated when compiling the other solution.
I can upload a zip of the source if it is needed.
Okay, the problem is not on CMake side, but with C++. When you used dllexport'ed class in your executable, its definintion should read class __declspec(dllimport) Other. This code works fine, for example:
#include <cstdio>
class __declspec(dllimport) Other {
public:
static int value;
int a();
};
int main(int argc, char *argv[]) {
printf("value = %d\n", Other::value);
return 0;
}
Here's a link with complete solution: https://social.msdn.microsoft.com/Forums/en-US/6c43599d-6d9d-4709-abf5-4d1e3f5e4fc9/exporting-static-class-members
I have read this informative stackoverflow question regarding unresolved external symbols, but I am still not sure how to solve my issue.
Within Visual Studio 2012, I have a solution consisting of multiple projects, one of which is a static library called common. Each project that produces an executable consists of a header and associated cpp file of all global functions used throughout that specific program, called programglobals. In the process of developing one of these projects, I started duplicating some of this code from one project's programglobals to another. Now that I have completed all the projects, I want to extract the duplicate code into a associated header and cpp file within the common library, but I believe I might be referencing them incorrectly, which is producing these unresolved external symbol errors
Here is a dumbed down example of what I am currently attempting.
Common Library Files
//solutionglobals.h
void commonFunction();
//solutionglobals.cpp
void commonFunction() {
int asdf;
}
Project A Files
// programglobals.h
#include "../common/solutionglobals.h
void functionUsedInProjectA();
// programglobals.cpp
void functionUsedInProjectA() {
int x;
}
// output.h
#include "programglobals.h"
void asdfA();
// output.cpp
void asdfA() {
int x;
functionUsedInProjectA();
commonFunction();
}
Project B Files
// programglobals.h
#include "../common/solutionglobals.h
void functionUsedInProjectB();
// programglobals.cpp
void functionUsedInProjectB() {
int x;
}
// output.h
#include "programglobals.h"
void asdfB();
// output.cpp
void asdfB() {
int x;
functionUsedInProjectB();
commonFunction();
}
Any reference to commonFunction() results in an unresolved external symbol error.
Thanks!
You will have to specify in your executable projects that they reference the static lib. May be http://msdn.microsoft.com/en-us/library/vstudio/ms235627%28v=vs.110%29.aspx#uselibinapp helps (lower third of the article).
Before you can use the math routines in the static library, you must
reference it. To do this, open the shortcut menu for the MyExecRefsLib
project in Solution Explorer, and then choose References. In the
MyExecRefsLib Property Pages dialog box, expand the Common Properties
node, select Framework and References, and then choose the Add New
Reference button.
The linker cannot 'see' your function and as such thinks that it does not have an external symbol referencing it, hence the error.
You must #pragma comment(lib, [library here]) to reference the external function.
The following code can be used to reproduce this error:
[header file- test.h]:
#include "StdAfx.h"
void someOtherFunction();
void someFunction(string thisVar);
[code file- test.cpp]:
#include "StdAfx.h"
#include "test.h"
void someOtherFunction()
{
printf("Hello World!");
}
[function body for someFunction(string thisVar) is missing!]