I'm working on a Visual Studio solution with multiple projects (Visual Studio 2013). One project is for generating a .dll file, other projects use that .dll file and generate .exe files. When I export a standard type variable everything works fine. But in case if I want to use my custom defined type I get an compilation error. Here is an example
// Dll.cpp
#define DllExport __declspec (dllexport)
DllExport int maxPackSize = 20;
// my custom type
struct DllExport Header
{
int m_data; // some data
};
DllExport Header qHead = { 100 };
// Exe.cpp
#define DllImport __declspec (dllimport)
DllImport extern int packetSize; // OK
struct DllImport Header;
DllImport extern Header qHead; // leads to an error
When I use qHead in my Exe.cpp I get a compilation error on that line. Error is like
error C2027: use of undefined type 'Header'
What am I doing wrong? Any ideas?
The error message you get is a compiler error (not a linker error!).
You need to define Header prior to its first use.
You could move struct DllExport Header { ... }; to a separate header file (e.g. Dll.h) and then #include "Dll.h" in Exe.cpp.
You need to export your custom type in a header, so that your .exe can see the type. For example,
Dll.h
#ifdef EXPORT_SYMBOLS
#define DLL_EXPORT __declspec(dllexport)
#else
#define DLL_EXPORT __declspec(dllimport)
#endif
struct DLL_EXPORT Header
{
int m_data;
};
Exe.cpp
#include "Dll.h"
Header qHead;
You need to add EXPORT_SYMBOLS to the Dll's preprocessor flags so that the correct __declspec macro is switched.
Related
I have a set of functions written in C that I need to be able to call from another project written in C++. The C code is essentially some functions that do some calculations on a large data set. I didn't write them - all I want to do is allow my C++ project to be able to call those functions. My solution was to create a DLL for the C code and link it to my C++ project.
In order to make the DLL, I structured myCproj.h (the header in the C project, not C++ project) like so:
#ifdef __cplusplus
extern "C" {
#endif
struct __declspec(dllexport) neededStruct {
int a;
//I need to be able to initialize this struct in my C++ project.
}
__declspec(dllexport) void neededFunc( struct neededStruct *input ) {}
//I need to be able to call this function from my C++ project and feed
//it my local instance of neededStruct.
#ifdef __cplusplus
}
#endif
The src file, myCproj.c, was not changed at all. The function definitions do not have __declspec(dllexport)in front of them, nor is extern "C" inserted anywhere. The code compiles without error and produces myCproj.dll and myCproj.lib.
I then tell my C++ project in VS where to find myCproj.lib and myCproj.h accordingly and copy the DLL over to the directory where my C++ executable lives. To use the DLL, I gave myCPPproj.cpp the following addition:
#define DLLImport __declspec(dllimport)
struct DLLImport neededStruct input;
input.a = 0;
extern "C" DLLImport void neededFunc( &input );
However, I get error EO335 'linkage specification is not allowed' on that last line. What am I doing wrong?
It is preferable to use the same header for both the library and using code.
As mentioned, it is usually done by a conditional define, like the following:
MyLibrary.h:
#if defined(MYLIBRARY_API)
#define MYLIBRARY_EXPORTS __declspec(dllexport)
#else
#define MYLIBRARY_EXPORTS __declspec(dllimport)
#endif
#if defined(__cplusplus)
extern "C" {
#endif
MYLIBRARY_API bool MyLibFunc();
#if defined(__cplusplus)
#endif
MyLibrary.c:
#include "MyLibrary.h"
void MyLibFunc()
{
....
}
App.cpp:
#include <MyLibrary.h>
int main()
{
MyLibFunc();
}
The symbol MYLIBRARY_API will be defined for the library project (usually as a /D on the compiler command line). And if you use visual studio that is pretty much exactly what you get when creating a dll project with exports.
i am trying to generate dll file, use its .lib file in another program ,but unfortunately, no .lib file is generated!
what should i do?
Try it like this:
extern "C" _declspec (dllexport) int add(int a, int b);
extern "C" _declspec (dllexport) int add(int a, int b)
{
return a + b;
}
You'll need to use __declspec (two underscores) with dllexport attribute to export a symbol from a DLL. And on client side you'll need to use __declspec(dllimport).
You better put the declaration on header like this:
// YourHeader.H
#ifdef _DLL_EXPORTING // Define this symbol in DLL project setting
#define EXPORT_IMPORT __declspec(dllexport)
#else
#define EXPORT_IMPORT __declspec(dllimport)
#endif
EXPORT_IMPORT int add(int,int);
Let the client use this header directly without worrying about declspec specifier. The EXPORT_IMPORT macro can also be used to export any other functions you want to export/import.
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.
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