Exposing .lib methods through another DLL - c++

I have the following setup in my solution (all C++):
Project1, compiled as static library (.lib).
Project2, compiled as DLL, includes the .lib generated in 1.
Project3, includes the DLL generated in 2.
Now I want to expose functions of project1 to project3, without directly including the .lib of project 1. I keep having linker errors.
error LNK2001: unresolved external symbol
Project 1 is set up to use dllexport and dllimport in the following way (FOO_API is in front of the classes / methods to expose as well of course):
#if defined(FOO_STATIC)
#define FOO_API
#define FOO_TEMPLATE(type) template class type
#else
#ifdef FOO_EXPORTS
#define FOO_API __declspec(dllexport)
#define FOO_TEMPLATE(type) template class FOO_API type
#else
#define FOO_API __declspec(dllimport)
#define FOO_TEMPLATE(type) extern template class FOO_API type
#endif
#endif
Since we compile Project1 as a static library, the dllexport path won't be taken (we define FOO_STATIC). Via the DLL of Project2 however, I want to expose the methods of Project1. I tried to create a .cpp file in Project2 that defines FOO_EXPORTS and then includes the headers of the files containing the methods I want to export. So:
// somefile_that_will_be_built.cpp
#define FOO_EXPORTS
#include "a.h"
#include "b.h"
#include "c.h"
My hope was that this would trigger the dllexport code in Project1 so it would be included in the DLL of Project2. I hoped that when Project3 included Project1 headers it would go the dllimport path and than the linker would find the required methods. So:
#include "a.h"
class WrapThis:
public:
SomeMethodInA();
Project3 compiles, but during linking the SomeMethodA() is not found. Is my approach not possible? Do I need to write a module definition file in Project2 instead? I would hope to prevent this as we have some name ambiguity, and name mangling does not help either (I know this can be turned off, but I wouldn't want to do this for other reasons).
Any help would be appreciated as my experience in this part of development is limited.
UPDATE
Remaining errors (took 4 as example):
2>Stdafx.obj : error LNK2028: unresolved token (0A000683) "public: void __cdecl fooEx::Load(char const * const)" (? Load#fooEx#Namespace4#Namespace1#Namespace2#Namespace3##$$FQEAAXQEBD#Z) referenced in function "public: void __clrcall Namespace1::Namespace2::Namespace3::Namespace4::FooEx::Load(class System::String ^)" (?Load#FooEx#Namespace4#Namespace1#Namespace2#Namespace3##$$FQE$AAMXPE$AAVString#System###Z)
2>Stdafx.obj : error LNK2028: unresolved token (0A000684) "public: void __cdecl fooEx::LoadHeader(char const * const)" (?LoadHeader#fooEx#Namespace4#Namespace1#Namespace2#Namespace3##$$FQEAAXQEBD#Z) referenced in function "public: void __clrcall Namespace1::Namespace2::Namespace3::Namespace4::FooEx::LoadHeader(class System::String ^)" (?LoadHeader#FooEx#Namespace4#Namespace1#Namespace2#Namespace3##$$FQE$AAMXPE$AAVString#System###Z)
2>Stdafx.obj : error LNK2028: unresolved token (0A000686) "public: void __cdecl fooEx::Save(char const * const,double,double)" (?Save#fooEx#Namespace4#Namespace1#Namespace2#Namespace3##$$FQEAAXQEBDNN#Z) referenced in function "public: void __clrcall Namespace1::Namespace2::Namespace3::Namespace4::FooEx::Save(class System::String ^,double,double)" (?Save#FooEx#Namespace4#Namespace1#Namespace2#Namespace3##$$FQE$AAMXPE$AAVString#System##NN#Z)
2>Stdafx.obj : error LNK2028: unresolved token (0A000687) "public: void __cdecl fooEx::Save(char const * const)" (?Save#fooEx#Namespace4#Namespace1#Namespace2#Namespace3##$$FQEAAXQEBD#Z) referenced in function "public: void __clrcall Namespace1::Namespace2::Namespace3::Namespace4::FooEx::Save(class System::String ^)" (?Save#FooEx#Namespace4#Namespace1#Namespace2#Namespace3##$$FQE$AAMXPE$AAVString#System###Z)
Project1 - classA (compiled with FOO_EXPORT) into static lib.
class FOO_API fooEx : public foo
{
public:
fooEx();
virtual void Free();
void Load(const char filename[]);
void LoadHeader(const char filename[]);
virtual void LoadRawData();
void Save(const char filename[]);
}
May be important:
Project1 uses precompiled headers.
Load & LoadHeader are defined in multiple files in the exact same way (other extensions of foo class).
virtual methods are defined in the base class as well as in the other implementations of that base class.
Project2 - Compiled as DLL. Includes Project1.lib via Linker input, additional dependencies.
Project3 - Compiled as DLL. Example class that has methods that cannot be linked.

This cannot work of course, the .lib code was compiled with the wrong #define in effect. So its functions won't be exported.
You'll either have to rebuild the .lib with FOO_EXPORTS defined or write a .def file that lists the functions that must be exported. Rebuilding is of course by far the least painful solution, you could simply add another configuration to the lib project and include the project in your DLL solution. Or always build the lib with FOO_EXPORTS defined, it is still a static library that can be linked into a non-DLL project.

All the compiled binary code for project1 is contained within the .lib file.
You can't use it from another project without including it at compilation time.
You could redefine the parts of project1 that you wish to share at run time as a shared library (i.e. a DLL).

Related

error LNK2019: unresolved external symbol CheckLr referenced in function

legitmate_relationship.dll : Basically this dll is consumed for one of the unit test project unittest_legitimate_relationship.
As soon as I build unittest_legitimate project, giving some linker errors.
error LNK2019 : unresolved external symbol CheckLr referenced in function "private: bool __cdecl LrTester::LrTest()
here is function defalcation which i am going to call in my unit test project,and which is declared in "legitmate_relationship.h " header file
#ifdef __cplusplus
extern "C"
{
#endif
DLL_IMPORT (bool_t)
CheckLr(STD_HANDLE hPrincipal, STD_HANDLE hCollectionIn, STD_HANDLE hCollectionOut);
#ifdef __cplusplus
}
function is defined like this in file "lrrule.cpp"
DLL_EXPORT (bool_t)
CheckLr(STD_HANDLE hCollectionIn, STD_HANDLE hCollectionOut, STD_HANDLE hPrincipal)
{
}
In order to make use of checklr function in unittest_legitimate project, I have added the .lib file reference in addional dependence . So that the function definition should be available for project.
If I am compiling unittest-legitimate project, I am getting linker errors as mentioned above.
call made to checklr() in lrtest.cpp :
CheckLr((STD_HANDLE)permissionCollectionIn, (STD_HANDLE)permissionCollectionOut, (STD_HANDLE)principal);
I am not sure how to resolve such kind of linker errors.Thanks in advance.
1.Three things to check, the legitimaterelasionship.dll project and unittest_legitimate-relationship.exe project should be the same:
MT/MD
x86/x64
cplusplus/c
2.The legitimaterelasionship.dll project generates a legitimaterelasionship.lib file. The unittest_legitimate-relationship.exe project should link to this legitimaterelasionship.lib file.

Unresolved externals when compiling unit tests for Visual C++ 2012

I want to create unit tests for a Visual C++ project. I tried following these MSDN instructions. I've found pages where they differentiate between unmanaged/mixed/pure code, but I don't fully understand those concepts. My code doesn't use .NET and would likely compile under MinGW with a few code adjustments.
My main project builds an executable, so I followed the steps under To reference exported functions from the test project. For starters I got different project options:
I went with Native Unit Test Project. I added a reference to my main project and I set Include Directories to $(SolutionDir)\Cubes;$(IncludePath). I wrote my code and got this when compiling:
1>Creating library C:\Users\Pieter\Dropbox\Unief\TTUI\TTUIproject\Cubes\Debug\CubesTest.lib and object C:\Users\Pieter\Dropbox\Unief\TTUI\TTUIproject\Cubes\Debug\CubesTest.exp
1>LayoutTest.obj : error LNK2019: unresolved external symbol "public: __thiscall Room::Room(void)" (??0Room##QAE#XZ) referenced in function "public: void __thiscall CubesTest::LayoutTest::NumOfRoomsConsistency(void)" (?NumOfRoomsConsistency#LayoutTest#CubesTest##QAEXXZ)
1>LayoutTest.obj : error LNK2019: unresolved external symbol "public: __thiscall Layout::Layout(class Room *,int)" (??0Layout##QAE#PAVRoom##H#Z) referenced in function "public: void __thiscall CubesTest::LayoutTest::NumOfRoomsConsistency(void)" (?NumOfRoomsConsistency#LayoutTest#CubesTest##QAEXXZ)
1>LayoutTest.obj : error LNK2019: unresolved external symbol "public: void __thiscall Layout::add(int,int,class Room *)" (?add#Layout##QAEXHHPAVRoom###Z) referenced in function "public: void __thiscall CubesTest::LayoutTest::NumOfRoomsConsistency(void)" (?NumOfRoomsConsistency#LayoutTest#CubesTest##QAEXXZ)
1>LayoutTest.obj : error LNK2019: unresolved external symbol "public: void __thiscall Layout::clear(int,int,bool)" (?clear#Layout##QAEXHH_N#Z) referenced in function __catch$?NumOfRoomsConsistency#LayoutTest#CubesTest##QAEXXZ$0
1>C:\Users\Pieter\Dropbox\Unief\TTUI\TTUIproject\Cubes\Debug\CubesTest.dll : fatal error LNK1120: 4 unresolved externals
If I'm not mistaken, this means that the compiler finds the header files, but not the source files. What am I missing?
Here is a step-by-step description on how to add an EXE as an unit-test target.
The key point is to "export" the functions/classes you want to test... You can download the complete sample here: http://blog.kalmbachnet.de/files/CPP_UnitTestApp.zip (I did not change any project settings, so all changes you can see in the source-code; of course, some parts can be made in the project settings).
Create a Win32 Application (Console or MFC or Windows, does not matter); I created a console project called CPP_UnitTestApp:
Add a function you want to test (you can also add classes). For example:
int Plus1(int i)
{
return i+1;
}
Add a header file for the functions you want to test: CPP_UnitTestApp.h
Put the declaration of the methods into the header file, and also export these functions!
#pragma once
#ifdef EXPORT_TEST_FUNCTIONS
#define MY_CPP_UNITTESTAPP_EXPORT __declspec(dllexport)
#else
#define MY_CPP_UNITTESTAPP_EXPORT
#endif
MY_CPP_UNITTESTAPP_EXPORT int Plus1(int i);
Include this header file in the main-cpp (here CPP_UnitTestApp.cpp) and define the EXPORT_TEST_FUNCTIONS before including the header:
#define EXPORT_TEST_FUNCTIONS
#include "CPP_UnitTestApp.h"
Now add a new project (Native unit test project: UnitTest1)
Include the header and the lib to the "unittest1.cpp" file (adopt the paths as you want):
#include "..\CPP_UnitTestApp.h"
#pragma comment(lib, "../Debug/CPP_UnitTestApp.lib")
Go to the project settings of the test project add add a reference to the "UnitTest1" project (Project|Properties|Common Properties|Add New Reference...: Select under "Projects" the "CPP_UnitTestApp"-Project)
Create the unit test function:
TEST_METHOD(TestMethod1)
{
int res = Plus1(12);
Assert::AreEqual(13, res);
}
Run your unit test ;)
As you can see, the main point was to export the function declaration! This is done via __declspec(dllexport) even if it is an EXE.
As I said, the demo project can be downloaded here: http://blog.kalmbachnet.de/files/CPP_UnitTestApp.zip

unresolved external symbol for __declspec(dllimport) when using dll to export class

I want to define a derived class based on a dll exported class. The base class is defined in Project A, and the derived class is in Project B.
Firstly, in Project A, preprocessor MYDLL_BUILD is defined. And I use a header file to specify export/import:
#if !defined(MYDLL_BUILD)
# pragma comment(lib, "myDll.lib")
#endif
#if defined(MYDLL_BUILD)
# define MYDLL_API __declspec(dllexport)
#else
# define MYDLL_API __declspec(dllimport)
#endif
Then I define the base class:
class MYDLL_API DllObject
{
public:
virtual ~DllObject() {}
protected:
DllObject() { m_count = 3; }
private:
int m_count;
};
In Project B, the preprocessor MYDLL_BUILD is not defined. Here is the derived class:
class MyClass : public DllObject
{
public:
~MyClass(){}
MyClass() { m_data = 20; }
private:
int m_data;
};
I have included the dll and lib file, but still I get the unresolved external symbol error:
2>Test_Entry.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: virtual __thiscall ADAI::DllObject::~DllObject(void)" (__imp_??1DllObject#ADAI##UAE#XZ) referenced in function "public: virtual __thiscall MyClass::~MyClass(void)" (??1MyClass##UAE#XZ)
2>Test_Entry.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) protected: __thiscall ADAI::DllObject::DllObject(void)" (__imp_??0DllObject#ADAI##IAE#XZ) referenced in function "public: __thiscall MyClass::MyClass(void)" (??0MyClass##QAE#XZ)
2>c:\Users\Adai\Documents\Visual Studio 2010\Projects\Test_Main\Debug\Test_Main.exe : fatal error LNK1120: 2 unresolved externals
I searched online, most of the answers claim that the lib is missing. But those instructions do not solve my problem.
When I change
class MYDLL_API DllObject
to
class __declspec(dllexport) DllObject
The solution compiles with no error. I really do not understand the reason. Can someone please help? Thanks in advance.
The reason is inlining.
In short, to make inline functions possible C++ must allow the same definition of function to be included and compiled in multiple compilation units (basically .cpp files) without causing errors. Compiler can, but doesn't have to emit code for any of this definitions. Then linker is allowed to chose one copy.
This complicates dll creation because you need to export exactly one copy but compiler doesn't know which copy is the right one. In this case by adding some code to DllObject.cpp you made the compiler emit code for DllObject and linker had some copy of DllObject::~DllObject to export.
I cannot give you more detailed explanation of your particular case because I don't know full source and compilation options for your project.
I had the same issue today. I was including the .dll and .lib files from my version of DllObject, But it wasn't helping.
To fix, What I had to do was add the .lib files name to my MyCLass version's project's Properties->Linker->Input->Additional dependencies.
If this doesn't work, You might want to add the .lib location's directory address in Properties->Linker->General->Additional library directories.

Linker error when trying to link to a dll

I have a Dll Which has 4 files Header files-1.StreamReader.h 2.StreamWriter.h Source Files-StreamReader.cpp 2.StreamWriter.cpp in windows VS2008.
StreamReader.h
Class StreamReader{
public:
static __declspec(dllexport) StreamReader* GetInstance();
//other functions
private:
StreamReader(){}
~StreamReader(){}
static StreamReader *m_pInstance;
};
StreamReader.cpp
StreamReader *StreamReader::m_pInstance=NULL;
StreamReader *StreamReader::GetInstance()
{
return((m_pInstance==NULL)?m_pInstance=new StreamReader:m_PInstance);
}
//other functions
I have a very similar structure for StreamWriter and a GetInstance() there as well.
When I link to this dll statically in a exe it complains during compilation
error LNK2001: unresolved external symbol "private: static class
StreamReader * StreamReader::m_pInstance"
(?m_pInstance#StreamReader##0PAV1#A)
error LNK2019: unresolved
external symbol "public: static class StreamReader * __cdecl
StreamReader::GetInstance(void)"
(?GetInstance#StreamReader##SAPAV1#XZ) referenced in function _main
The exe is also written in c++. But it can find StreamWriter symbol. The StreamWriter and StreamReader files are essentially the same except for the fact that one reads and one writes to a file. What am i missing? Thank you
Make sure the .cpp files are actually in the project and not just in the folder. That way, the compiler knows to compile them and produce the object files that the linker is looking for.
When you import a dll you need to have dllimport declared.
You have
static __declspec(dllexport) StreamReader* GetInstance();
you need
static __declspec(dllimport) StreamReader* GetInstance();
you can use the same header file for this by using a preprocessor definition
#ifdef _EXPORTING
#define CLASS_DECLSPEC __declspec(dllexport)
#else
#define CLASS_DECLSPEC __declspec(dllimport)
#endif
static CLASS_DECLSPEC StreamReader* GetInstance();
make sure to add _EXPORTING preprocessor definition to the project that exports the DLL

C++ linker unresolved external symbol (again;) from other source file *.obj file. (VC++ express)

I'm back to C/C++ after some break.
I've a following problem:
I've a solution where I've several projects (compilable and linkable).
Now I need to add another project to this solution which depends on some sources from other projects.
My new project compiles without any problems (I've added "existing sources" to my project).
the error:
1>Linking...
1>LicenceManager.obj : error LNK2019: unresolved external symbol "int __cdecl saveLic(char *,struct Auth *)" (?saveLic##YAHPADPAUAuth###Z) referenced in function "public: void __thiscall LicenceManager::generateLicence(int,char *)" (?generateLicence#LicenceManager##QAEXHPAD#Z)
1>LicenceManager.obj : error LNK2019: unresolved external symbol "void __cdecl getSysInfo(struct Auth *)" (?getSysInfo##YAXPAUAuth###Z) referenced in function "public: void __thiscall LicenceManager::generateLicence(int,char *)" (?generateLicence#LicenceManager##QAEXHPAD#Z)
Functions saveLic, and getSysInfo are defined in files which I've added to my new project from existing ones. There is object file created during compilation with those functions in target dir, but my LicenceManager class doesn't want to link.
I use some
extern "C" , and #pragma pack
somewhere, but no more fancy stuff. I think every directory, lib and other necessary dependencies are visible in settings for this project.
Thanks for any advice.
Seems like you need to make sure the functions are declared properly as C functions:
#ifdef __cplusplus
extern "C" {
#endif
int saveLic(char *,struct Auth *);
void getSysInfo(struct Auth *);
#ifdef __cplusplus
}
#endif
In a header file included by LicenceManager.cpp.