Well, I have been struggling with this for days now. I am writing a custom game DLL for CryENGINE from scratch, and I cannot even get the solution compile with one simple class (Game.cpp) and a precompiled header (StdAfx.h).
Both Game.cpp and StdAfx.cpp will compile perfectly on their own, but compiling the solution throw tons of multiply defined errors. The class is simple because the definitions are just placeholders.
Game.h
#if !defined __GAME__H__
#define __GAME__H__
#pragma once
class CGame : public IGame
{
public:
CGame();
VIRTUAL ~CGame();
//IMPLEMENT: IGame Interface, all methods declared.
};
#endif
Game.cpp
#include "StdAfx.h" //PreComp header
#include "Game.h"
//Define all methods, each one has a simple definition.
StdAfx.h
#if !defined __STDAFX__H__
#define __STDAFX__H__
#pragma once
//Various CryENGINE includes
#endif
Output
error LNK2005: "struct SSystemGlobalEnvironment * gEnv" (? gEnv##3PEAUSSystemGlobalEnvironment##EA) already defined in StdAfx.obj
error LNK2005: "public: static long volatile _CryMemoryManagerPoolHelper::allocatedMemory" (?allocatedMemory#_CryMemoryManagerPoolHelper##2JC) already defined in StdAfx.obj
error LNK2005: "public: static long volatile _CryMemoryManagerPoolHelper::freedMemory" (?freedMemory#_CryMemoryManagerPoolHelper##2JC) already defined in StdAfx.obj
error LNK2005: "public: static long volatile _CryMemoryManagerPoolHelper::requestedMemory" (?requestedMemory#_CryMemoryManagerPoolHelper##2JC) already defined in StdAfx.obj
error LNK2005: "public: static int volatile _CryMemoryManagerPoolHelper::numAllocations" (?numAllocations#_CryMemoryManagerPoolHelper##2HC) already defined in StdAfx.obj
The list goes on...
What really throws me off is that each one will compile just fine individually, so syntax and references are good. What could possibly cause multiply defined errors when the solution is compiled as a whole?
I really appreciate help on this frustrating issue, thank you.
I'm not sure the errors are caused by the precompiled header, but here is the correct way to set up the precompiled header:
Right-click on the project name in Solution Explorer, select Properties, go to Configuration Properties | C/C++ | Precompiled Headers and set the Precompiled Header setting to Use (/Yu). Leave the other two settings below it to the default.
Right-click on StdAfx.cpp, go to the same setting and set it to Create (/Yc).
Well, I figured it out. There is a clever complex include that does not belong in the precompiled header:
#include <Platform_Impl.h>
This was causing all my problems, and by moving it to Game.cpp, everything is fine.
Related
I am using SFML's audio libraries.
In my class I tried to have a private static variable that holds a SoundBuffer* as such:
static sf::SoundBuffer* breakBlockBuffer;
This gives a linker error when I try to build:
Chunk.obj : error LNK2001: unresolved external symbol "private: static class sf::SoundBuffer * Chunk::breakBlockBuffer" (?breakBlockBuffer#Chunk##0PAVSoundBuffer#sf##A)
myprogram.exe : fatal error LNK1120: 1 unresolved externals
However, if I declare it as an instance variable, it works:
sf::SoundBuffer* breakBlockBuffer;
This happens regardless of whether I dynamically link or statically link the libraries. It also persists in both SFML1.6 and SFML2.0.
I'm feeling that I might have made some silly mistake since I'm pretty rusty at C++, but the code looks like it should be ok to me.
If you declare a static variable in your class, you must also define it on your source file:
foo.hpp:
class foo
{
static int bar;
};
foo.cpp:
int foo::bar;
Looks like you didn't do it.
I have C++ managed dll compiled with /clr that has some global functions.
for example
void Managed2UnManaged(DataStructures::AAA^ elem, DataStructures::CPP::AAA* copy_elem);
when I try to use these functions in a C++ managed console application I get the following errors
error LNK2028: unresolved token (0A00048C) "void __clrcall Managed2UnManaged(class DataStructures::AAA ^,class DataStructures::CPP::AAA *)" (?Managed2UnManaged##$$FYMXP$AAVAAA#DataStructures#NextIn##PAV1CPP#23##Z)
error LNK2019: unresolved external symbol "void __clrcall Managed2UnManaged(class DataStructures::AAA ^,class DataStructures::CPP::AAA *)" (?Managed2UnManaged##$$FYMXP$AAVAAA#DataStructures#NextIn##PAV1CPP#23##Z)
I added to the console application a reference to the dll but it still gives the error.
I also tried adding __declspec(dllexport) but then I get
error C3395: 'Managed2UnManaged' : __declspec(dllexport) cannot be applied to a function with the __clrcall calling convention
and if I specify __stdcall I get
error C4439: 'Managed2UnManaged' : function definition with a managed type in the signature must have a __clrcall calling convention
I am using VS2012.
the h file has
class XXX {
public:
static void Managed2UnManaged(DataStructures::RegResult^ elem, DataStructures::CPP::RegResult* copy_elem);
};
and the cpp file
void XXX::Managed2UnManaged(DataStructures::RegResult^ elem, DataStructures::CPP::RegResult* copy_elem)
{
}
Problem Solved. the problem was that I also needed to declare the class public ref. this caused a different problem because that the native c++ types are private. so I had to use the make_public pragma.
Thanks all.
I think that the problem may be that the CLR doesn't allow global functions.
You must create a managed class and write your function as a static member function of that class, for that function to be exported.
This is the header of a class I am working on in Visual C++ Express 2010:
/* custom class header to communicate with LynxMotion robot arm */
#include <vector>
using namespace System;
using namespace System::IO::Ports;
public ref class LynxRobotArm
{
public:
LynxRobotArm();
~LynxRobotArm();
void connectToSerialPort(String^ portName, int baudRate);
void disconnectFromSerialPort();
void setCurrentPosition(int channel, int position);
int getCurrentPosition(int channel);
void moveToPosition(int channel, int position);
private:
void initConnection();
SerialPort^ serialPort;
array<String^> ^serialPortNames;
String^ portName;
int baudRate;
vector<int> currentPosition;
};
Everything worked fine until I changed the last line int currentPosition to vector<int> currentPosition. If I try to compile / debug now, I get these error messages:
error C2143: syntax error : missing ';' before '<'
error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
error C2238: unexpected token(s) preceding ';'
I checked MSDN for some more info on these error codes, but I cannot figure out what is wrong with the code. Any ideas?
vector is template defined within std namespace, thus you should write std::vector<int> instead of vector<int>.
Alternatively you could write using namespace std; at the beginning of this file, but note that this is considered bad practice since it could cause some of names of your classes to become ambiguous.
You are using vector. Vector is contained with the namespace std. Namespaces encapsulate the normal scope of a variable/class. You cannot access elements within a namespace without resolving the scope somehow. There are 3 main ways to go about this:
#include <vector>
using namespace std;
You don't generally want to use this one, it will create issues because it allows you to see ANY function/class contained in the namespace std. This is bound to cause naming collisions.
Next way is:
#include <vector>
using std::vector;
This way is a little better. It makes vector visible to anything in the file or any file that includes said file. It is perhaps completely harmless in a .cpp file, because you shouldn't be including .cpp files anyways. And you should know what symbols you're or not. In the scenario of a .h/.hpp file, you may still not want to use this. Any file that has your .hpp file included their source code will see class vector as the name definition. This could be bad for users of your code, because they may not be expecting that symbol to be defined. In the case of an hpp file, you should always use the following:
#include <vector>
class myClass{
private:
std::vector myVector;
};
Using namespaces this way guarantees that it will only be visible exactly where the symbol is used, and nowhere else. This is the only way I'd use it in a .hpp file.
How do I export the methods of a native class defined in a C++/CLI project? Here's what I have:
The .h file:
#pragma once
#ifdef COMPILE_PRODUCER_LIB
#define PRODUCER_LIB_EXPORT __declspec(dllexport)
#else
#define PRODUCER_LIB_EXPORT __declspec(dllimport)
#endif
public class PRODUCER_LIB_EXPORT MySecondNativeClass {
public:
MySecondNativeClass(int val);
int getValue() const;
private:
int m_value;
};
The .cpp file:
#include "stdafx.h"
#include "MySecondNativeClass.h"
MySecondNativeClass::MySecondNativeClass(int val) {
this->m_value = val;
}
int MySecondNativeClass::getValue() const {
return this->m_value;
}
Using this class in the same project works fine, but using it in another (C++/CLI) project gives me "unresolved external symbol" linker errors. (COMPILE_PRODUCER_LIB is a preprocessor definition defined only in the project that contains the class.)
I've created a small solution (for Visual Studio 2010) that shows the problem (download at the end of this page). There, the native class MySecondNativeClass is defined in the project "ManagedProviderLib" and is being used in "ExternalTestClass.cpp" (in project "ManagedExternalLib").
Your DLL project creates a .lib file in the build directory, the DLL's import library. You need to specify that .lib file in the other project, Linker + Input, Additional Dependencies setting.
Note that Add Reference cannot work, the assembly metadata only contains definitions for managed classes. Your class is native C++, not managed. Also make sure that your .cpp file is compiled without /clr in effect. The C++/CLI compiler will happily translate native C++ classes to IL but that is not very efficient. You can control this within the source code file with #pragma managed.
Precondition
environment : VC2005
I encountered this problem when discovered circular dependency in my project(two dll references each other), so divide either of one dll to two dll's.
explain with example :
typedef struct { <br>
char myFileName[MAX_PATH];
} MyStructure;
Before :
MyHeader.h
MyStructure globalStruct;
After:
MyCommon.h
#ifdef _MYGLOBAL_
#define API __declspec(dllexport)
#else
#define API __declspec(dllimport)
#endif
API extern MyStructure globalStruct;
MyGlobal.c
API MyStructure globalStruct;
MySpecific.c
API MyStructure globalStruct;
failed code after changed: (this code run in specific dll)
handle = LoadLibrary(globalStruct.myFileName);
I confirmed globalStruct.myFileName values are same(at lease real words).
I can't access the value directly with debugger after changed. so, to see value in debugger, I copyed to temp local char[] variable. And then, I found before value and after value are different in tailing dummy char's.
before:
d:[my path] '0'(char end null) '0' '0' ...
after:
d:[my path] '0'(char end null) '-3' '-3' '-3' ...
thank you for your reading.
self-solved my problem.
This is because dll does not re-compiled after my circular dependency removal work.
So, this problem is not related import/export global variable but dll re-compile issue.
Sorry for my ugly question.