what I've got here is pretty much a dumb and noobie question, but I just can`t find an answer on the web.
When I want to create a DLL project (out of an existing c++ project), I read that I need to implement the following lines in the beginning of the .h files:
#ifdef _EXPORTING
#define CLASS_DECLSPEC __declspec(dllexport)
#else
#define CLASS_DECLSPEC __declspec(dllimport)
#endif
I looked at the example in the MSDN:
// MathFuncsDll.h
#ifdef MATHFUNCSDLL_EXPORTS
#define MATHFUNCSDLL_API __declspec(dllexport)
#else
#define MATHFUNCSDLL_API __declspec(dllimport)
#endif
Now I want to understand, do I need to change the "_EXPORTING" and the "CLASS_DECLSPEC" for every new class I make?
For example if I'd create a class named "foo" within the same project as "MathFuncsDll.h" I'd need to put the following lines at the start of the .h file:
// FooDll.h
#ifdef FOO_EXPORTS
#define FOO_API __declspec(dllexport)
#else
#define FOO_API __declspec(dllimport)
#endif
Or is some line is the same in all .h files of the project?
And another thing, if I use a namespace to reference the whole dll as one and extract the classes from it, do I need to put the using namespace *NAME* in every .h file?
No, you need not to create new macros for each classes:
class MATHFUNCSDLL_API Foo {...};
class MATHFUNCSDLL_API Boo {...};
class MATHFUNCSDLL_API MyNewClass {...};
For the second q: don't use using namespace inside header file: "using namespace" in c++ headers
Your header can looks like the following:
#pragma once
namespace foo {
class MATHFUNCSDLL_API Foo {...};
class MATHFUNCSDLL_API Boo {...};
class MATHFUNCSDLL_API MyNewClass {...};
}
EDITED
// mylibdef.h
#pragma once
#ifdef _EXPORTING
#define CLASS_DECLSPEC __declspec(dllexport)
#else
#define CLASS_DECLSPEC __declspec(dllimport)
#endif
// myclass1.h
#pragma once
#include "mylibdef.h"
namespace mylib {
class CLASS_DECLSPEC MyClass1 {...};
}
// myclass2.h
#pragma once
#include "mylibdef.h"
namespace mylib {
class CLASS_DECLSPEC MyClass2 {...};
}
Related
I have C project from which I export function f() and call it from other C++ project and it works fine. However, when I call some other function g() inside f I get LNK2028 error.
The minimal example of Cproject looks like:
Test.h
#ifndef TEST_H
#define TEST_H
#include "myfunc.h"
#define EXTERN_DLL_EXPORT extern "C" __declspec(dllexport)
EXTERN_DLL_EXPORT void f()
{
g(); // this will provide LNK2028 if f() is called from other project
}
#endif
myfunc.h
void g();
myfunc.c
#include "myfunc.h"
void g(){}
The project itself is being built. However, when I call this function from other C++/CLIproject
#include "Test.h"
public ref class CppWrapper
{
public:
CppWrapper(){ f(); } // call external function
};
I get error:
error LNK2028: unresolved token (0A00007C) "void __cdecl g(void)" (?g##$$FYAXXZ) referenced in function "extern "C" void __cdecl f(void)" (?f##$$J0YAXXZ) main.obj CppWrapper
error LNK2019: unresolved external symbol "void __cdecl g(void)" (?g##$$FYAXXZ) referenced in function "extern "C" void __cdecl f(void)" (?f##$$J0YAXXZ) main.obj CppWrapper
Additional details:
I set x64 platform for whole solution
In CppWrapper I include .lib file from C project
Test.h
#ifndef TEST_H
#define TEST_H
#ifdef BUILDING_MY_DLL
#define DLL_EXPORT __declspec(dllexport)
#else
#define DLL_EXPORT __declspec(dllimport)
#endif
#ifdef __cplusplus
extern "C" {
#endif
DLL_EXPORT void f();
#ifdef __cplusplus
}
#endif
#endif
Test.c
#include "Test.h"
#include "myfunc.h"
void f()
{
g();
}
In your C project you have to add BUILDING_MY_DLL to
Configuration Properties > C/C++ > Preprocessor > Preprocessor Definitions
The only real change is that I added the toggle between __declspec(dllexport) and __declspec(dllimport). Changes required:
Moved f's body to Test.c because functions imported with __declspec(dllimport) cannot have a definition already.
Other changes:
Do never write extern "C" without an #ifdef __cplusplus guard, or many C compilers will not compile your code.
I just spent 2 days fighting this exact same problem. Thank you for the solution. I'd like to extend it.
In my case, I am calling a c function from an exported c++ dll function and I was getting the same error. I was able to fix it so (using your example)
#ifndef TEST_H
#define TEST_H
#ifdef BUILDING_MY_DLL
#define DLL_EXPORT __declspec(dllexport)
#else
#define DLL_EXPORT __declspec(dllimport)
#endif
#ifdef __cplusplus
extern "C" {
#endif
#include "myfunc.h"
#ifdef __cplusplus
}
#endif
#endif
I'm attempting to get a toy program running with AVT's VIMBA SDK. At the moment, it is going well save for one caveat. When I attempt to compile, I get a series of errors (14 of them) that all are marked same thing:
function *insert call here* definition is marked dllimport
The file itself is below- the curious thing is that in in this file, only ~IFeatureObserver(), IFeatureObserver(), and IFeatureObserver( const IFeatureObserver& ) are triggering the error; FeatureChanged() does not error out during a compile.
#ifndef AVT_VMBAPI_IFEATUREOBSERVER_H
#define AVT_VMBAPI_IFEATUREOBSERVER_H
#include <VimbaCPP/Include/VimbaCPPCommon.h>
#include <VimbaCPP/Include/SharedPointerDefines.h>
#include <VimbaCPP/Include/Feature.h>
#include <vector>
namespace AVT {
namespace VmbAPI {
class IFeatureObserver
{
public:
IMEXPORT virtual void FeatureChanged( const FeaturePtr &pFeature ) = 0;
IMEXPORT virtual ~IFeatureObserver() {}
protected:
IMEXPORT IFeatureObserver() {}
IMEXPORT IFeatureObserver( const IFeatureObserver& ) { /* No copy ctor */ }
};
typedef std::vector<IFeatureObserverPtr> IFeatureObserverPtrVector;
}} // namespace AVT::VmbAPI
#endif
After tracking down source of IMEXPORT, I found it in a .h file.
#if defined (_WIN32)
#if defined AVT_VMBAPI_CPP_EXPORTS // DLL exports
#define IMEXPORT __declspec(dllexport)
#elif defined AVT_VMBAPI_CPP_LIB // static LIB
#define IMEXPORT
#else // import
#define IMEXPORT __declspec(dllimport)
#endif
#elif defined (__GNUC__) && (__GNUC__ >= 4) && defined (__ELF__)
#define IMEXPORT
#elif defined (__APPLE__)
#define IMEXPORT
#else
#error Unknown platform, file needs adaption
#endif
I am currently programming in Qt on a Win7-32 bit machine, and as far as I can tell IMEXPORT is being defined as __declspec(dllimport).
Thoughts? Thanks in advance!
You should define the macro AVT_VMBAPI_CPP_EXPORTS in your makefile or VS project. This way IMEXPORT is defined as dllexport for this library and dll import when other libraries/app use it.
BTW it's cleaner to add this attribute to the class itself, not every function.
class IMEXPORT IFeatureObserver {
public:
virtual void FeatureChanged( const FeaturePtr &pFeature ) = 0;
};
Say I have the following .h and .cpp files for a DLL:
.h
#ifdef BLAH_EXPORTS
#define BLAH_API __declspec(dllexport)
#else
#define BLAH_API __declspec(dllimport)
#endif
class BLAH_API MyClass
{
public:
static void SomeFunction();
};
.cpp
#include ".h" //you get the picture
void MyClass::SomeFunction()
{
//blah blah blah
}
Now you import the .dll and .lib for this DLL into another program.
Is it possible to create a thread of MyClass::SomeFunction() since it's hidden in a DLL?
I can't quite figure out where there is a mistake. I am creating a DLL and then using it in a C++ console program (Windows 7, VS2008). But I get LNK2019 unresolved external symbol when trying to use the DLL functions.
First the export:
#ifndef __MyFuncWin32Header_h
#define __MyFuncWin32Header_h
#ifdef MyFuncLib_EXPORTS
# define MyFuncLib_EXPORT __declspec(dllexport)
# else
# define MyFuncLib_EXPORT __declspec(dllimport)
# endif
#endif
This is one header file I then use in:
#ifndef __cfd_MyFuncLibInterface_h__
#define __cfd_MyFuncLibInterface_h__
#include "MyFuncWin32Header.h"
#include ... //some other imports here
class MyFuncLib_EXPORT MyFuncLibInterface {
public:
MyFuncLibInterface();
~MyFuncLibInterface();
void myFunc(std::string param);
};
#endif
Then there is the dllimport in the console program, which has the DLL included in the Linker->General->Additional Library Directories:
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
__declspec( dllimport ) void myFunc(std::string param);
int main(int argc, const char* argv[])
{
std::string inputPar = "bla";
myFunc(inputPar); //this line produces the linker error
}
I can't figure out what's going wrong here; it must be something really simple and fundamental.
You're exporting a class member function void MyFuncLibInterface::myFunc(std::string param); but trying to import a free function void myFunc(std::string param);
Make sure you #define MyFuncLib_EXPORTS in the DLL project. Make sure you #include "MyFuncLibInterface.h" in the console app without defining MyFuncLib_EXPORTS.
The DLL project will see:
class __declspec(dllexport) MyFuncLibInterface {
...
}:
And the console project will see:
class __declspec(dllimport) MyFuncLibInterface {
...
}:
This allows your console project to use the class from the dll.
EDIT: In response to comment
#ifndef FooH
#define FooH
#ifdef BUILDING_THE_DLL
#define EXPORTED __declspec(dllexport)
#else
#define EXPORTED __declspec(dllimport)
#endif
class EXPORTED Foo {
public:
void bar();
};
#endif
In the project which actually implements Foo::bar() BUILDING_THE_DLL must be defined. In the project which tries to use Foo, BUILDING_THE_DLL should not be defined. Both projects must #include "Foo.h", but only the DLL project should contain "Foo.cpp"
When you then build the DLL, the class Foo and all its members are marked as "exported from this DLL". When you build any other project, the class Foo and all its members are marked as "imported from a DLL"
You need to import the class not a function. After that, you can call the class member.
class __declspec( dllimport ) MyFuncLibInterface {
public:
MyFuncLibInterface();
~MyFuncLibInterface();
void myFunc(std::string param);
};
int main(int argc, const char* argv[])
{
std::string inputPar = "bla";
MyFuncLibInterface intf;
intf.myFunc(inputPar); //this line produces the linker error
}
I can't export a class:
#ifndef SDBIDI
#define SDBIDI
#ifndef SDBIDI_FLAG
#define SDBIDI_ORIENT __declspec(dllimport)
#else
#define SDBIDI_ORIENT __declspec(dllexport)
#endif
#include "TCInfoSuVars.h" //class is here!
SDBIDI_ORIENT int myFoo(FILE *file); // exporting function
#endif
class definition in TCInfoSuVars.h
#pragma once
#include <string>
#include <hash_map>
class SDBIDI_ORIENT TCInfoSuVars
{
public:
std::string id;
std::string tcVal;
TCInfoSuVars();
TCInfoSuVars(std::string _tcVal, std::string _id);
~TCInfoSuVars();
};
Getting a error:
myProgram.cpp
#define SDBIDI_FLAG
output:
TCInfoSuVars.h(14) : error C2470: 'TCInfoSuVars' : looks like a function definition, but there is no parameter list; skipping apparent body
And if I write
class __declspec(dllexport) TCInfoSuVars
everything works OK.
Thank you!
Somewhere you're including TCInfoSuVars.h before SDBIDI_ORIENT is defined - Make sure you include the header file that defines SDBIDI_ORIENT first.