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).
Related
I have a starter project and I need to write a custom allocator and diagnostic tools for it. I made a class Class in which I have 2 methods for the custom allocator void alloc() void dealloc() and for the diagnostic tools void evaluate().Now, I declared an object test of type Class in CustomAllocator.h and use the 2 methods to allocate and deallocate memory with no problems. But when I try to call the evaluate() method in CustomAllocatorTest.cpp I got the linker error class Class test(?test##3VClass##A) already defined in CustomAllocatorTest.obj and LNK1169 one or more multiply defined symbols found.
Class.h
#pragma once
class Class
{
public:
void alloc() { std::cout << "alloc"; }
void dealloc() { std::cout << "dealloc"; }
void evaluate() { std::cout << "evaluate"; }
};
CustomAllocator.h
#ifndef _CUSTOM_ALLOCATOR_H_
#define _CUSTOM_ALLOCATOR_H_
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#include <stdlib.h>
#include "Class.h"
Class test;
#endif // _CUSTOM_ALLOCATOR_H_
CustomAllocator.cpp (#include "stdafx.h" includes "CustomAllocator.h")
#include "stdafx.h"
using namespace std;
int main()
{
test.evaluate();
return 0;
}
in your file CustomAllocator.h you declare test in global scope :
#ifndef _CUSTOM_ALLOCATOR_H_
#define _CUSTOM_ALLOCATOR_H_
#include "Class.h"
Class test; // <-- Declaration of test
#endif
But your CustomAllocator.h is included many times, in many places (in UseCustomAllocator.h and CustomAllocator.cpp) which will generate an already defined error for test variable.
Please see how to declare externe globale variable here #pragma once doesn't prevent multiple variable definitions
I have a my.h file:
#ifndef __MY__
#define __MY__
#include <string>
#include <time.h>
class S
{
public: S();
std::string myname;
};
#endif
my.cpp
#include "my.h";
#include<string>
#include<iostream>
using namespace std;
S::S()
{
// .. code
}
I want to create an so file. There is no error when creating it. But when I compile the .h file it says: string:No such file or directory. If I pus string.h instead of string I have the error: expected '=',',',';','asm', before S (at class S) in my.h.
In the .cpp file (if i change the string with string.h) i have after i compile error: string in namespace std does not name a type. WHERE AM I WRONG?
Well, first, it seems that you come from java because when you typed:
class S
{
public: S();
std::string myname;
};
I guess you actually meant:
class S
{
public:
S();
private:
std::string myname;
};
In the .cpp file, you typed s instead of S: note that C++ is case-sensitive regarding classes names.
Also, regarding your problem, I suspect you are currently using a C compiler and not a C++ compiler. Without knowing the used command-line, I can't say much more on that.
Try this
#ifndef MY_H
#define MY_H
#include <string>
#include <time.h>
class S
{
public: S();
std::string myname;
};
#endif
#include "my.h"
#include<string>
#include<iostream>
using namespace std;
S::S()
{
//code
}
Here's the whole code getting the errors:
Engine.h
#ifndef ENGINE_H
#define ENGINE_H
#include "DXManager.h"
namespace XEngine
{
class Engine
{
};
}
#endif
DXManager.h
#ifndef DX_MANAGER_H
#define DX_MANAGER_H
namespace XEngine
{
class Engine; // forward declaration
class DXManager
{
public:
void run(Engine *engine);
};
}
#endif
DXManager.cpp
#include <iostream>
#include "Engine.h"
#include "DXManager.h"
using namespace XEngine;
void DXManager::run(Engine *engine)
{
std::cout<<"DXManager::run"<<std::endl;
}
With these 30 lines of code, I'm getting 20 errors like:
'XEngine' : a namespace with this name does not exist
'XEngine' : a symbol with this name already exists and therefore this name cannot be used as a namespace name
syntax error : identifier 'Engine'
Clearly, I'm missing something important here. What am I doing wrong?
note: I am aware that circular dependency is a bad thing, but in my particular case I believe that it is relevant.
In DXManager.cpp you are not just using some names from namespace XEngine. You define the function in that namespace.
So must be:
DXManager.cpp
#include <iostream>
#include "Engine.h"
#include "DXManager.h"
namespace XEngine {
void DXManager::run(Engine *engine)
{
std::cout<<"DXManager::run"<<std::endl;
}
}
AFAIK some of the compilers (like MSVC) process using variant too.
But it is not correct because your syntax tries to define function ::DXManager::run - not ::XEngine::DXManager::run you intend to define.
In the forward-declaration of class Engine the namespace XEngine doesn't exist at this point.
A workaround would be moving the declaration inside the namespace block.
When Engine.h includes DXManager.h, the latter defines a class XEngine::Engine without declaring the namespace first.
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've looked around for a while, tried quite a few different approaches to this issue, but still cannot seem to get past errors occurring from forward declaration in a program with 3 codependent classes.
Here's a abstracted view of my current code's structure, split into 6 files + 1 main program file:
File x.h:
#ifndef X_H
#define X_H
using namespace std;
class y;
class x
{
private:
y *m_oY;
public:
// constructors &c
};
#endif
File x.cpp:
#include "x.h"
#include "y.h"
// Fancy stuff...
File y.h:
#ifndef Y_H
#define Y_H
using namespace std;
class z;
class y
{
private:
z *m_oZ;
public:
// constructors &c
z *funcZ()
};
#endif
File y.cpp:
#include "y.h"
#include "z.h"
// Fancy stuff...
File z.h:
#ifndef Z_H
#define Z_H
using namespace std;
class z { ... };
#endif
File z.cpp:
#include "z.h"
// Fancy stuff...
File main.cpp:
#include "z.h"
#include "y.h"
#include "x.h"
#include <iostream>
using namespace std;
int main() { ... }
The first error I receive, trying to compile in VS with a clean, non-PCH, non-ATL project occurs in my implementation when trying to use Class z. The error tells me that it's using the definition of z from y.h, and I'm not sure how to remedy this without creating a circular include problem. Text of the error follows:
main.cpp(114) : error C2514: 'z' : class has no constructors
y.h(9) : see declaration of 'z'
Any clues as to what I'm doing wrong here?
This isn't a forward declaration problem. Main.c can see the full declaration of class z. It must be that z has no constructor, at least of the proper shape, or maybe it is private.