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
}
Related
I have three projects in my visual studio solution: project A, project, B, and project C. Projects A and B compile to A.lib and B.lib, respectively, and project C compiles to C.dll. I'd like to take the functions in A.lib and B.lib and put them in C.dll - what can I do to make this happen? I have a feeling that I'm using __declspec(dllexport) at the wrong time, or that I'm forgetting to link something.
=== PROJECT A ===
foo.h
#include <iostream>
__declspec(dllexport) void foo();
foo.cpp
#include "foo.h"
void foo()
{
std::cout << "Foo!\n";
}
=== PROJECT B ===
goo.h
#include <iostream>
__declspec(dllexport) void goo();
goo.cpp
#include "goo.h"
void goo()
{
std::cout << "Goo!\n";
}
=== PROJECT C ===
// What goes here?
There is no need to use __declspec(dllexport) in static libraries.
foo.h can be modified as:
#include <iostream>
void foo();
Do not forget to add lib file in Dll's properties. For your reference: Create and use a static library and Create and use your own Dynamic Link Library (C++)
MyDLL:
Header.h
#pragma once
#include"foo.h"
#include"goo.h"
#ifdef MATHLIBRARY_EXPORTS
#define MATHLIBRARY_API __declspec(dllexport)
#else
#define MATHLIBRARY_API __declspec(dllimport)
#endif
extern "C" MATHLIBRARY_API void Myfun();
Cpp file
#include"Header.h"
void Myfun()
{
foo();
goo();
}
The test project:
#include <iostream>
#include"Header.h"//from MyDll
int main()
{
Myfun();
}
In test project, I only input Mydll.lib. And I also include directories of foo.h and goo.h.
Output:
Foo!
Goo!
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;
};
I did not realize in a .dll library object types that depends on things that happen at compile time can case problems until I read the question Could I ignore C4251 warning in this case? In deed, if the library compilation settings for the library and the program that uses the library are different, some errors can occur. Here is an example:
dll.h
#include <iostream>
#include <string>
using namespace std;
class __declspec(dllexport) HelloWorld
{
public:
#ifdef DTEST
int test;
#endif
HelloWorld();
};
dll.cpp
#include "dll.h"
HelloWorld::HelloWorld()
{
#ifdef DTEST
test=0;
#endif
}
exe.cpp
#include "dll.h"
#include <iostream>
using namespace std;
int main(void)
{
HelloWorld myworld;
return 0;
}
If I compile dll.h and dll.cpp to create dll.lib and dll.dll with the definition of DTEST but compile exe.cpp without the definition of DTEST. I will have a runtime check failure #2 error. Could some explain why I have this error. Thanks!
You have this error because DTEST is a preprocessor macro and you are not defining it consistently for all pieces of your program. It is completely removed by the time your code reaches the actual compiler, so the compiler won't catch the problem. If you define DTEST for dll.cpp but not for exe.cpp, then exe.cpp will look like this to the compiler:
(...contents of <iostream>...)
(...contents of <string>...)
using namespace std;
class __declspec(dllexport) HelloWorld
{
public:
HelloWorld();
};
(...contents of <iostream> again...)
using namespace std;
int main(void)
{
HelloWorld myworld;
return 0;
}
However, dll.cpp will look like this:
(...contents of <iostream>...)
(...contents of <string>...)
using namespace std;
class __declspec(dllexport) HelloWorld
{
public:
int test;
HelloWorld();
};
HelloWorld::HelloWorld()
{
test=0;
}
The problem here is dll.cpp and exe.cpp have two different ideas of what HelloWorld is: dll.cpp thinks it contains test, but exe.cpp thinks it doesn't. There is a runtime check that catches this mismatch, which is what you're seeing.
What the compiler sees is the results of preprocessor expansion.
In your example, the compiler sees:
class HelloWorld
{
public:
int test;
HelloWorld();
};
in dll.cpp, and
class HelloWorld
{
public:
HelloWorld();
};
in exe.cpp. Same class, two different definitions. That's
a violation of the one definition rule, which results in
undefined behavior.
This has nothing to do with the C4251 warning (which if
I understand correctly, only concerns linking between different
DLLs).
I have an application code which invokes a DLL lib with explicit linkage (or run time linking) for accessing an exported class.
DLL.h
#ifdef DLL_EXPORT
#define DLL_API __declspec(dllexport)
#else
#define DLL_API __declspec(dllimport)
#endif
FooDLL.h
#include "DLL.h"
class DLL_API Foo
{
public:
void doSomeThing();
};
extern "C" DLL_API Foo* _getInstance() {
return new Foo();
}
typedef Foo* (*getInstanceFactory)();
Foo* getInstance() {
HINSTANCE dllHandle = LoadLibraryA("Foo.dll");
getInstanceFactory factory_func = (getInstanceFactory)GetProcAddress(dllHandle, "_getInstance");
return factory_func();
}
FooDLL.cpp
#include "FooDLL.h"
Foo::doSomething() {
// .......
}
Application.cpp (which invokes DLL)
#include "FooDLL.h"
Foo* obj = getInstance();
obj->doSomething(); // XXX this line can be compiled and linked only when DLL is already in path
The above code can be built (e.g. compiled&linked) only when the DLL file is included in lib path. Otherwise I got unresolved external symbol error.
error LNK2001: unresolved external symbol "__declspec(dllimport) public: void __thiscall Foo::doSomething()" .....
Is it possible to build the application code with only DLL header file (i.e. FooDLL.h) and without DLL/LIB files during the build time? (p.s. The class implementation must be in cpp file.)
thanks!
with virtual function.
class Foo
{
public:
void virtual doSomeThing();
};
Yes it is possible. If you did not export a class you would not need a header file at all.
I am not sure why you placed call to LoadLibrary in the header file.
Since you are exporting class, you have to let the compiler know the type. Besides, you do not have to export entire class, you can export only specific member functions of the class you want to expose
Your dll header to be used in a dll and exe projects, should include following (I used my own names):
#ifdef WIN32DLL_EXPORTS
#define WIN32DLL_API __declspec(dllexport)
#else
#define WIN32DLL_API __declspec(dllimport)
#endif
class CWin32DLL
{
public:
CWin32DLL();
int WIN32DLL_API GetInt();
};
Implementation:
#include "stdafx.h"
#include "Win32DLL.h"
extern "C" WIN32DLL_API CWin32DLL* _getInstance()
{
return new CWin32DLL();
}
// This is the constructor of a class that has been exported.
// see Win32DLL.h for the class definition
CWin32DLL::CWin32DLL()
{
}
int CWin32DLL::GetInt()
{
return 42;
}
Your DLL consumer:
#include "Win32DLL.h"
#include "SomeOther.h"
typedef CWin32DLL* (*getInstanceFactory)();
HINSTANCE dllHandle = LoadLibrary(_T("Win32DLL.dll"));
getInstanceFactory factory_func = (getInstanceFactory)GetProcAddress(dllHandle, "_getInstance");
CWin32DLL* pWin32 = factory_func();
int iRet = pWin32->GetInt();
Do not forget to define WIN32DLL_EXPORTS (or equivalent) in project properties, C++, Preprocessor, Preprocessor Definitions for the dll.
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.