I'm trying to compile some other people's wrapper program on a large system, in which it's using a global object from another file, the definition of the class is like:
class __declspec(dllexport) A
{
...
static A * instance;
}
And in my separate source file (which I want to build to a .exe), I included the header file A.h, and declare at the beginning like this
A * A::instance;
to access the data in A.
The problem is, this piece of code can be built successfully on Linux, now when I try to build it in windows NT, it will have issues.
If I leave it like this, the compiler will complain with a C2491 error, definition of dllimport function not allowed.
If I remove this line of A declaration, I'll get a lot of error LNK2001: unresolved external symbol.
Not quite sure what is the problem here, I did some research online, but couldn't find a good answer, I myself is not that familiar with dll import/export and some C++ tricks either. Can some one provide some insights on the problem or which direction should I spend my time on to figure this out?
Or say, if I already have a static object like this, and I want to write another program to access it, how exactly should I do?
Please also correct me if I made any mistakes here. Thanks!
I think the keyword you need is extern, as in:
extern A *A::instance;
This says the variable A::instance is defined somewhere else, but you're telling the compiler about it so you can use it by name in this file.
__declspec(dllexport) is used when you want to export your function in a DLL. It should not be necessary as long as you're not calling the class from another DLL.
But I suspect your problem is related to using .c files and not the class specification. Try to read this by the way. It discusses dllexport in just-enough-detail Windows & C++: extern & __declspec(dllimport)
Singleton usually has a function, like
A::instance = NULL;
A * get_instance() {if (!A::instance) A::instance = new A; return A::instance;}
If you have a function like this you don't have to access A::instance directly.
And sorry, but what are you doing? Including a C++ header in a C program? Does it even compiles?
Personally I usually hide the instance in the .cpp file in an anonymous namespace. Then I provide a getInstance() function that returns a pointer or reference to it and I dllExport that function.
If you want to enforce things you can make the constructors for A private and make getInstance a friend.
Related
I am currently working on a project with some old poorly documented code, and am trying to navigate my way through the various .h files that they have provided complete documentation on the use of all of the functions contained (the definitions are held in .lib and .dll files). One of the .h files has functions the are not only declared, but defined with either simple return statements or empty statements as such
class DLL ExampleLibraryClass {
public:
int exampleGetValue() {return 0;}
void exampleSetValue(Type val) {;}
void exampleActionFxn() {;}
};
These would be functions that I expect to return current variable states or perform certain actions, which is why this puzzles me.
Additionally:
I have used Dependency Walker and found that each function does have a matching definition in a dll.
The Keyword DLL has been defined with
#ifndef _PWSDLL_
# define _PWSDLL_
# define WINCALL _stdcall
# ifdef _USRDLL
# define DLL __declspec(dllexport)
# else
# define DLL __declspec(dllimport)
# endif
#endif
_USRDLL is not defined and therefore DLL is defined as __declspec(dllimport)
My question revolves less about the apparent effect of the empty definitions (which do nothing I suppose, and have already been discussed on SO) and more about why the .h file has been written this way and how to utilize the file. Is this a common or known practice? Will the linker still look for definitions to the function in my linked libraries? Are there other pieces of code that I should look for for more clues? Or perhaps in the broadest sense, how should I respond to this?
Many thanks, and please let me know if you need more information to address this, I am unsure what exactly is important in this matter.
EDIT: Added forgotten return types in example code.
EDIT: Added note about DLL definition.
One scenario where you put this code to some use would be to override the functions. These functions hold some default code and could be overridden later.
This question might be similar to
DLL Exports: not all my functions are exported
but as it was not fully answered there, I have to ask again. Also my case is because of the use of templates and exporting the whole classes slightly different.
Used environment: VS2008, cl9.0.
I have created a dll-project and added about 40 files (each class a file), mainly headers, because a lot of the classes are templates. An example of the heritage would be:
// Class1.h
template<class TYPE>
class TInt
{
// Some member functions here
// Also a function bool IsValid() const;
};
// Implementation of template here in the header
// Class2.h
#ifndef DllExpImpM
#define DllExpImpM __declspec(dllimport)
#endif
class DllExpImpM CInt : public TInt<double>
{
// Some member functions here
};
// Class2.cpp
// Some includes, including "stdafx.h", which sets DllExpImpM
// to __declspec(dllexport)
template class DllExpImpM TInt<double>;
// Implemenation of CInt
So far, it worked fine as long as I used the debug (compile) option. I was able the use the dll project from other projects.
But if the dll projekt is compiled as release (which works fine), I cannot use it from other projects, because the compiler complains that are some missing functions, e.g. that IsValid() in TInt. I used the dependency walker to check it, and indeed, the compiler is right! The member function IsValid() was not exported, along with another function and with a constructor und the destructor. All other member functions of TInt are exported, I can see them using the dependency walker, I can use them from other projects. This also happens in a similar way with one other class.
I then compared the debug dll and the release dll using the dependency walker and winmerge. They are almost identical, just that the release dll is missing a few functions (about 3 %).
I have no idea what is wrong. I know that I do not have a lot information (the whole information is much too big and I yet could not find a simple example that does not work) and to me all sounds a little bit weird. But perhaps anyone out there once had the same problem. I appreciate every idea very much.
Thank you!
If it works for debug, but not release, then you need to identify what is different. My first guess would be that a #define macro or an equivalent /D macro us not getting defined or is getting defined wrongly.
Maybe DllExpImpM or maybe something else.
If not a macro, then what else changes between builds?
Here are some things I found when I ran into this.
I had the same issue, but taking off the /GL parameter didn't make any difference.
My first test was creating a very simple funcion - void test () - and trying to export it. That didn't work until I got rid of the whole output directory (x64 in my case) and rebuilt it all. It would guess that some intermediate file was messing my compilation, anyway, I didn't investigate it further.
But there was still one function that wouldn't be exported. I took some time to realize the declaration in the .h file wasn't matching exatly the signature in the .cpp file! I was missing a parameter in the .h file... I don't know why it was even compiling, anyway, fixing that allowed the function to be exported.
I am a little out of my depth here, I'll be honest.
I am doing some rather curious experimentation, having pre-main functions register my classes in a factory, through anonymous namespaces. Until recently, adding the following to a class definition (.cpp) would do the trick.
namespace { int x = Register<classType>(className); }
This would be wrapped in a macro and 'Register' would pass the type and name off to my factory.
This worked fine and every class that included this macro was getting registered, until I went to move the code into a static library. Now, since the classes are only referenced by the factory, it looks like they're being omitted from the build - my 'Register' functions are no longer being called and so my factory is empty.
I have managed to fix this by moving all my macros into the constructor of a manager object, but I noticed that as soon as I referenced them there, the macros in the .cpp files started getting called again. I guessed because now the classes are actually being referenced by something.
However, I don't really want to do it this way and I can't seem to find a non-committal way of referencing the classes in the constructor (e.g class ClassToRegister;) which includes them in the build, so that my register macros will get called.
Firstly, does this make sense?
Secondly, any advice on how I can force these TUs to compile so that the anonymous namespaces 'kick in' at runtime?
It appears this is part and parcel of using static libraries; unused code will not make it through without linker voodoo.
A static library is a bunch of object files you give the linker saying "hey, find here what I didn't define elsewhere". So if a given object file in the library doesn't fill a dependency, you won't be able to include it in your program without relying on other features of the linker (for instance some linkers have a way to include all the object files of static libraries instead of only the one who fill dependencies).
Most likely you are a victim of aggressive optimisation, but with a reason : since you do not use objects in a nameless namespace, the compiler removes them.
You could try to get around like this :
namespace foo
{
namespace{
MACRO_TO_DEFINE_VARIABLE( MyClass ); // define a variable named registrationObj
};
MyClass::MyClass()
{
(void)registrationObj;
}
}
I'm trying to understand some C++ code which has the following class syntax:
class Q_MONKEY_EXPORT BasePlugin : public QObject
{
// some code comes here
};
I cannot understand the syntax class Q_MONKEY_EXPORT BasePlugin. To me it looks like if there are two names for the class. What exactly does this kind of syntax mean in C++?
Q_MONKEY_EXPORT is most likely a #define somewhere. Defines like that are sometimes required, for example when the class is in a library and needs to be exported when the header file is included from somewhere else. In that case, the define resolves to something like __declspec(dllexport) (the exact syntax will depend on the tools you are using).
That's most probably a preprocessor directive telling the compiler the symbol is to be exported.
It's probably defined as:
#define Q_MONKEY_EXPORT _declspec(dllexport)
which will cause your class to be exported to the dll.
The full declaration will be expanded, before compilation, to:
class _declspec(dllimport) BasePlugin : public QObject
{
// some code comes here
};
EDIT:
As David Heffernan pointed out, macros like these are generally used to let the compiler know whether it needs to import or export the symbols. Usually defined as dllimport for outside modules and dllexport when building the module. I doubt that's the case here, since the name suggests exporting, but it's best to check the documentation or actually go to the definition.
Q_MONKEY_EXPORT is a macro (all upper case is convention for macro) that typically resolves to something like __declspec(dllexport) when you are building the DLL and resolves to __declspec(dllimport) when you are using the DLL.
You can find out exactly what it is by reading your include files.
I'm just a beginner in c++ and to me this seems like unnecessary code bloat. I understand that dllimport/export are used for sharing dll functionality, but what's wrong with just using public/private accessors?
If i am making a large dll library it seems that I have to go through every single function/class and make sure I export it. With managed dll (like from c#) I don't need to do anything. Import it into my project, and as long as the function is public it's accessible!
Because when you're creating a larger dll (or shared library) you may want to compose it of several object files, but don't want to expose all the public (to the linker) symbols in each object file. That is there are occations when a symbol is public in one of the object file for the only purpose to make it available to another object file in the same library.
Note that public and private accessors are not quite the same as private symbols in an object file. While private symbol in an object (fx created with global static qualifier) file means that the symbol is not visible at all outside the object file, while private accessors just mean that the symbol can't be accessed from outside the class (it still can make it into the object file as public since it could be accessed from the same class within another translation unit).
If you want to export all public symbols in the object files there may be a mechanism to do that without having to resort to explicitely mark each symbol as dllexport - you have to check the documentation, apparently there's a way in microsoft for that.
And for the story about dllimport you can read it here: Why/when is __declspec( dllimport ) not needed?
The idea is that your module can have some functionality that only it needs to run which exposing would be pointless. For example, if you have a Timer class you are exporting, and it depends on some global function you wrote to get the current time, you don't need to export said function, since users of your library don't depend on it directly.
Sorry about the bad example.. Also, you don't need to export your classes, use interfaces and factory functions.
//IBob.h
#define DLLAPI __cdecl
class IBob
{
public:
void DoSomething( ) = 0;
};
__declspec(/*export / import*/) IBob* DLLAPI BobFactory( );
//----------------------------------
//Bob.h
#include "IBob.h"
class Bob : public IBob
{
public:
void DoSomething( ) override
{
//implementation...
}
private:
int var;
int var2;
};
__declspec(dllexport) IBob* DLLAPI BobFactory( )
{
return new Bob( );
}
As said this is nothing to do with C++ and is just the way DLLs work in every language (.NET managed DLLs are different). When the OS loads a program with DLLs it must fix up all references in the EXE to functions exported from the DLL, so the less of them you use the faster the program loads. Probably in this day and age it makes little difference, but this goes back to the early versions of Windows.
BTW you can __declspec(dllexport) a whole class, which is the slightly lazy way of doing it.