In visual studio I've set configuration type as .dll instead of .exe and because of that sometimes I need to use __declspec(dllexport) or __declspec(dllimport) . So I've created macros for them inside header file called "Core"
#pragma once
#ifdef B5_PLATFORM_WINDOWS
#ifdef B5_BUILD_DLL
#define B5_API __declspec(dllexport)
#else
#define B5_API __declspec(dllimport)
#endif // B5_BUILD_DLL
#else
#error Bos5 only supports Windows!
#endif // B5_PLATFORM_WINDOWS
I have a class "Application" inside of my namespace "Bos5" which uses BS_API
#pragma once
#include "Core.h"
namespace Bos5 {
class B5_API Application
{
public:
Application();
~Application();
void Run();
};
}
everything works fine inside this project but when I reference this to another project for some reason visual studio thinks B5_API is a class and "Application" isn't. therefore code below doesn't compile saying namespace Bos5 doesn't have struct or class called "Application"
#include <FinalBos5.h>
class Sandbox : public Bos5::Application
{
public:
Sandbox(){}
~Sandbox(){}
};
int main() {
}
I think this image can better explain what I'm saying
Okay I've fixed it. turns out problem was completely different thing. My preprocessor didn't save some of the definitions so in second project B5_API wasn't getting defined
Related
I have a base class (QIndicator) and I want to implement derived classes in DLLs. The DLL project in Visual Studio 2012 for a sample derived class has the following code:
header file with base class
#ifndef _DLL_COMMON_INDICATOR_
#define _DLL_COMMON_INDICATOR_
// define the DLL storage specifier macro
#if defined DLL_EXPORT
#define DECLDIR __declspec(dllexport)
#else
#define DECLDIR __declspec(dllimport)
#endif
class QIndicator
{
private:
int x;
int y;
};
extern "C"
{
// declare the factory function for exporting a pointer to QIndicator
DECLDIR QIndicator * __stdcall getIndicatorPtr(void);
}
#endif
source file with derived class
#define DLL_EXPORT
#include "indicator.h"
class QIndicatorDer : public QIndicator
{
public:
QIndicatorDer (void) : QIndicator(){};
~QIndicatorDer (void){};
private:
// list of QIndicatorDer parameters
int x2;
int y2;
};
extern "C"
{
DECLDIR QIndicator * __stdcall getIndicatorPtr(void)
{
return new QIndicatorDer();
};
}
The problem I have is that upon successful build, the produced DLL file does not contain the exported getIndicatorPtr function (as shown by DependencyWalker). I checked whether the dllexport keyword gets propagated properly into the declaration of getIndicatorPtr and it does.
Another interesting problem is that I already have another derived class like this, in another DLL project, that I created some months ago. This older project is basically the same and everything works well there. I checked all properties of both the old and the current projects, and they seem identical. So I ran out of ideas, why I can't get getIndicatorPtr to export.
Any help is much appreciated,
Daniel
That's because it's not being exported. Why?
__declspec specifier should only be placed in the declaration of a function, not it's definition. Also, avoid something like #define DLL_EXPORT. Preprocessor definitions should either defined in project properties (MSVC) or command line option (-D in GCC, for example).
Look at you code:
Header
extern "C"
{
DECLDIR QIndicator * __stdcall getIndicatorPtr(void);
}
When compiler parses this header, is sees DECLDIR as dllimport (because you define DLL_EXPORT in .cpp). Then in .cpp, it suddenly appears as dllexport. Which one is used? The first one.
So, leave your header (it's fine), but change your source:
//#define DLL_EXPORT -> remove this!
#include "indicator.h"
class QIndicatorDer : public QIndicator
{
//...
};
extern "C"
{
/* DECLDIR -> and this! */ QIndicator * __stdcall getIndicatorPtr(void)
{
return new QIndicatorDer();
};
}
Then, go to project properties (I assume you use Visual Studio) and then C/C++ -> Preprocessor -> Preprocessor Definitions and add there DLL_EXPORT=1.
That should work.
Just started doing some coding for a very simple automated test framework for internal use. (I know there are hundreds of them out there - really good ones too, but at the moment that's not interesting, so don't point me to any of those, please ;)) I then came across the following problem which I can't explain, thus asking for your help.
I have the following code as part of a DLL:
(The code is barely an embryo and took me <2 minutes to write, so it's logic, structure - nothing - is refined, in any way yet.)
h-file:
#pragma once
#ifdef __DLL__ // Defined in DLL-project
#define DLLEXPORT __declspec( dllexport )
#else
#define DLLEXPORT
#endif
class DLLEXPORT AutoTest
{
public:
enum eTestID {TESTID_SomeFunction};
AutoTest(eTestID id, LPVOID lpData)
{
if(sm_bTestsActive)
ExecTest(id, lpData);
}
void ActivateTests();
private:
static void ExecTest(eTestID id, LPVOID lpData)
{
}
static BOOL sm_bTestsActive;
};
cpp-file:
#include "StdAfx.h"
#include "AutoTest.hpp"
BOOL AutoTest::sm_bTestsActive = FALSE;
void AutoTest::ActivateTests()
{
sm_bTestsActive=TRUE;
}
This compiles just fine and the DLL gets generated.
Here's my problem though - when instantiating the class with:
AutoTest(AutoTest::TESTID_SomeFunction, &SomeData);
from the main application, the linker fails with
error LNK2001: unresolved external symbol "private: static int AutoTest::sm_bTestsActive" (?sm_bTestsActive#AutoTest##0HA)
<2 minutes to write - now going on 5 hours to understand why it fails!!! :O
Here's what interesting - if I move the constructor to the cpp-file (not inlined) it works just fine!?!?
Here's that code:
h-file:
#pragma once
#ifdef __DLL__ // Defined in DLL-project
#define DLLEXPORT __declspec( dllexport )
#else
#define DLLEXPORT
#endif
class DLLEXPORT AutoTest
{
public:
enum eTestID {FK3059};
AutoTest(eTestID id, LPVOID lpData);
void ActivateTests();
private:
static void ExecTest(eTestID id, LPVOID lpData)
{
}
static BOOL sm_bTestsActive;
};
cpp-file:
#include "StdAfx.h"
#include "AutoTest.hpp"
BOOL AutoTest::sm_bTestsActive = FALSE;
AutoTest::AutoTest(eTestID id, LPVOID lpData)
{
if(sm_bTestsActive)
ExecTest(id, lpData);
}
void AutoTest::ActivateTests()
{
sm_bTestsActive=TRUE;
}
(I've made some minor edits in the code after pasting, so there may or may not be simple syntax errors.)
Also, if I remove the reference to the static member from the inline versions constructor, it works fine.
Any ideas as to why the inline version won't work?
Pay attention to your definition of DLLEXPORT.
Make sure that it is properly expanded to __declspec(dllexport) when building the DLL, or __declspec(dllimport) when building the client.
I'd suggest using a macro with a more specific name than the generic DLLEXPORT (to avoid conflicts with other macros with the same name).
Having static data members accessed from inline member functions works fine for me (tested with VS2013).
Minimal repro:
Create a Visual Studio solution with an empty DLL project and an empty console application project.
Inside the DLL project add two files:
DllClass.h:
#pragma once
#ifndef TEST_DLL_CLASS
#define TEST_DLL_CLASS __declspec(dllimport)
#endif
class TEST_DLL_CLASS DllClass
{
public:
DllClass();
int GetMember() const
{
return m_data1;
}
static int GetStaticMember()
{
return sm_data2;
}
private:
int m_data1;
static int sm_data2;
};
DllClass.cpp:
#define TEST_DLL_CLASS __declspec(dllexport)
#include "DllClass.h"
int DllClass::sm_data2 = 2;
DllClass::DllClass()
: m_data1(1)
{
}
Inside the console app project, add one file:
Test.cpp:
#include "..\DllTestClass\DllClass.h"
#include <iostream>
using namespace std;
#pragma comment(lib, "DllTestClass")
int main()
{
DllClass dllClass;
cout << dllClass.GetMember() << endl;
cout << DllClass::GetStaticMember() << endl;
}
Make sure that when building the console test app, the linker can find the DLL .lib (DllTestClass.lib) file.
For that purpose, you can navigate the console app's project properties, going to:
Project Properties | Linker | Additional Library Directories
and add $(OutDir) to the additional library directories, making it:
$(OutDir);%(AdditionalLibraryDirectories)
Builds and works correctly for me.
Should be:
#ifdef __DLL__ // Defined in DLL-project
#define DLLEXPORT __declspec( dllexport )
#else
#define DLLEXPORT __declspec( dllimport )
#endif
You can declare C++ classes with the dllimport or dllexport attribute. These forms imply that the entire class is imported or exported. Classes exported this way are called exportable classes.
More information in the documentation.
I am using Visual Studio 2012 and I creared dll without using MFC, it generating the dll. But when I specify to generate a lib file in specific directory using the following option:-
go to proeperties page->Advanced->Import Library
../../../lib/myapp.lib
It is not genearting the lib file in the specified folder. Please help me .
Thanks & Regards
Vikas
Just resolved a similar problem. Visual Studio does not create a .lib file without instructing which objects to expose in dll. You need to create a win exports header like this:
#ifndef BLABLABLA
#define BLABLABLA
#ifdef MYAPPLIB_EXPORTS
#define MYAPPLIB_API __declspec(dllexport)
#elif defined(MYAPPLIB_EXPORTS_STATIC)
#define MYAPPLIB_API
#else
#define MYAPPLIB_API __declspec(dllimport)
#endif
#endif // !BLABLABLA
Then, you need to declare MYAPPLIB_EXPORTS as a preprocessor macro. After including this new header file in other API headers, for every class or method which you want to expose in your API, you can add MYAPPLIB_API to their declarations like:
class MYAPPLIB_API MyClass{ ... };
calculatelibrary.h
/*
By default, the New Project template for a DLL adds PROJECTNAME_EXPORTS to the defined preprocessor symbols for the DLL project.
In this example, CALCULATELIBRARY_EXPORTS is defined when your calculateLibrary DLL project is built.
When the CALCULATELIBRARY_EXPORTS symbol is defined, the CALCULATELIBRARY_API symbol sets the __declspec(dllexport) modifier on the member function declarations in this code.
This modifier tells the compiler and linker to export the function or variable from the DLL so that it can be used by other applications.
When CALCULATELIBRARY_EXPORTS is undefined—for example, when the header file is included by a client application—CALCULATELIBRARY_API defines the __declspec(dllimport) modifier on the member function declarations. This modifier optimizes the import of the function in an application. For more information
*/
#ifndef _calculate_library_h
#define _calculate_library_h
#ifdef CALCULATELIBRARY_EXPORTS
#define CALCULATELIBRARY_API _declspec(dllexport)
#else
#define CALCULATELIBRARY_API _declspec(dllimport)
#endif
namespace calculatelibrary
{
class CALCULATELIBRARY_API clsCalculateLibrary{
// Returns a + b
double Add(double a, double b);
};
}
#endif _calculate_library_h
// CalculateLibrary.cpp : Defines the exported functions for the DLL application.
//
#include "stdafx.h"
#include "CalculateLibrary.h"
namespace calculatelibrary
{
double clsCalculateLibrary::Add(double a, double b)
{
return a + b;
}
}
See the following: you may need to declare /EXPORTS (http://msdn.microsoft.com/en-us/library/7k30y2k5.aspx)
http://msdn.microsoft.com/en-us/library/67wc07b9.aspx see "REMARKS"
On the .dll file
//SWC.h
#ifndef _SWC_
# define _SWC_
# define SWC_CALL __declspec(dllexport)
#else
# define SWC_CALL __declspec(dllimport)
#endif
namespace SWC
{
struct SWC_CALL Mouse
{
//interface
};
class SWC_CALL SWC_Base : public someClass1, public someClass2
{
static Mouse mouse;
};
//other classes goes here...
}
//SWC_Base.cpp
namespace SWC
{
Mouse SWC_Base::mouse; //needed, to compile
//other SWC_Base function definition
}
On .exe file
with the static struct Mouse mouse I defined on the SWC_Base I get linking errors
I solve my problem by redefining it again on this file
//main.cpp
#include "SWC.h"
#pragma comment (lib, "..\\SWC")
SWC::Mouse SWC::SWC_Base::mouse; //<- why do I need to redefine it again?
int main()
{
//...
return 0;
}
I already define the SWC_Base::mouse on its .cpp file, why do I need to redefine it again on the file who uses it? I know I can have this more problems as my .dll project is growing with static variables on it.
If your calling code will use __declspec (dllimport) this trouble will be gone :)
#ifdef EXPORTING_SWC
#define SWC_CALL __declspec(dllexport)
#else
#define SWC_CALL __declspec(dllimport)
#endif
You have added an anymous namespace { } around your definition (in case that you posted the real code) in the header file. Each anonymous namespace will translated to a compilation unit specific namespace by the compiler. Therefore you get always a new class in a new namespace.
To solve the problem you can either
move the declaration, the defination, and all use to one source file
use a named namespace
I was following a tutorial on how to create a C++/Cli DLL, for some reason I get a warning for each function declaration, here's the whole code:
// KRecognizer.h
#pragma once
namespace KR
{
class __declspec(dllimport) KinectRecognizer
{
public:
KinectRecognizer();
~KinectRecognizer();
int Display();
};
}
_
// KRecognizer.cpp
#include "stdafx.h"
#include "KRecognizer.h"
using namespace System;
KR::KinectRecognizer::KinectRecognizer()
{
}
KR::KinectRecognizer::~KinectRecognizer()
{
}
int
KR::KinectRecognizer::Display()
{
Console::WriteLine(L"Writing a line");
return 100;
}
Here are the error outputs:
http://pastie.org/3678144
I'm compiling with the /clr flag.
The header declares DLL import, which means the definition of the class comes from a DLL. Since you are providing the definition, this gives the linkage error. You'll want to use __declspec(dllexport) instead when defining the DLL.
Since you'll want to use the same header file in the app that will use the DLL, the following idiom is often used:
#ifdef MYAPI_EXPORTS
# define MYAPI __declspec(dllexport)
#else
# define MYAPI __declspec(dllimport)
#endif
And then use:
class MYAPI KinectRecognizer
#define MYAPI_EXPORTS before including the header in the DLL, but do not define it in the application using the header to import the DLL.