SDK Question Atlantis sample not compiling - missing reference to VESSEL2

chalcrow

Donator
Donator
Joined
Nov 30, 2016
Messages
12
Reaction score
0
Points
0
I'm a complete Orbiter noob. I'm trying to compile the Atlantis sample from Orbiter 2016 using Visual Studio 2019 (preview version). I'm getting the following error in the Atlantis_SRB project:

Error LNK2019 unresolved external symbol "__declspec(dllimport) public: __thiscall VESSEL2::VESSEL2(class VESSEL2 &&)" (__imp_??0VESSEL2@@QAE@$$QAV0@@Z) referenced in function "public: __thiscall Atlantis_SRB::Atlantis_SRB(class Atlantis_SRB &&)" (??0Atlantis_SRB@@QAE@$$QAV0@@Z) Atlantis_SRB C:\Orbiter2016\Orbitersdk\samples\Atlantis\Atlantis_SRB.obj

So I understand that this means that I have a reference somewhere in the Atlantis_SRB project to a 'VESSEL2' class that's declared in a .lib file somewhere. Which .lib file is it declared in?

If I right-click the Atlantis_SRB project and select 'properties', then go to Linker > Input, I currently have the following specified for 'Additional Dependencies':

orbiter.lib;orbitersdk.lib;%(AdditionalDependencies);C:\Orbiter2016\Orbitersdk\lib\orbiter.lib;C:\Orbiter2016\Orbitersdk\lib\Orbitersdk.lib

(this is a bit messy - I've been trying different things!). The orbiter.lib and Orbitersdk.lib files are definitely present at the following locations:

C:\Orbiter2016\Orbitersdk\lib\orbiter.lib
C:\Orbiter2016\Orbitersdk\lib\Orbitersdk.lib

I've also added these 2 paths under:

Linker -> General -> Additional Library Directories

which now looks like this:

$(SDKLibDir);%(AdditionalLibraryDirectories);C:\Orbiter2016\Orbitersdk\lib;C:\Orbiter2016\Orbitersdk\lib\orbiter.lib;C:\Orbiter2016\Orbitersdk\lib\Orbitersdk.lib

I'm not sure if the VESSEL2 is even in the orbiter.lib or Orbitersdk.lib libraries?
 

Face

Well-known member
Orbiter Contributor
Addon Developer
Beta Tester
Joined
Mar 18, 2008
Messages
4,398
Reaction score
578
Points
153
Location
Vienna
Error LNK2019 unresolved external symbol "__declspec(dllimport) public: __thiscall VESSEL2::VESSEL2(class VESSEL2 &&)" (__imp_??0VESSEL2@@QAE@$$QAV0@@Z) referenced in function "public: __thiscall Atlantis_SRB::Atlantis_SRB(class Atlantis_SRB &&)" (??0Atlantis_SRB@@QAE@$$QAV0@@Z) Atlantis_SRB C:\Orbiter2016\Orbitersdk\samples\Atlantis\Atlantis_SRB.obj

So I understand that this means that I have a reference somewhere in the Atlantis_SRB project to a 'VESSEL2' class that's declared in a .lib file somewhere. Which .lib file is it declared in?

It is declared in the header files, but implemented in the library, so while the compiler step can compile the code, the linker can't link the symbols to the actual implementation. That's why you get a linker error.

I'd revert all the panic changes to the properties of the projects in order to start with a clean slate, and then try to get the property-pages (the files inside \Orbitersdk\resources\) right.
 

chalcrow

Donator
Donator
Joined
Nov 30, 2016
Messages
12
Reaction score
0
Points
0
Face, thanks so much. I'm just starting Orbiter and didn't expect any reply, so it's fantastic to get your advice! I'm an experienced software devleloper however I'm a complete C++ and Orbiter noob (I've done some Objective C and Python before and I'm usually C#).

I'll start again with the properties pages. This'll be the 3rd time starting fresh, and I did originally start with the properties pages tutorial by Andrew Stokes:


I got the idea that the properties pages are important which is why I followed the tutorial however I don't understand what the properties pages really do and why they're so important. In C# you don't normally need this kind of thing. Is this a normal thing to have to do in C++, or is setting up the properties pages a very specific requirement for Orbiter?

I'm finding it very frustrating to get started with Orbiter so any advice is great.
 

Face

Well-known member
Orbiter Contributor
Addon Developer
Beta Tester
Joined
Mar 18, 2008
Messages
4,398
Reaction score
578
Points
153
Location
Vienna
I'll start again with the properties pages. This'll be the 3rd time starting fresh, and I did originally start with the properties pages tutorial by Andrew Stokes:

Orbiter 2016 Props Files Tutorial - YouTube

I got the idea that the properties pages are important which is why I followed the tutorial however I don't understand what the properties pages really do and why they're so important. In C# you don't normally need this kind of thing. Is this a normal thing to have to do in C++, or is setting up the properties pages a very specific requirement for Orbiter?

The problem is that the original property pages were done with VS 2008 IIRC, but M$ changed the format (or compatibility) with newer VS versions.

I'll take a look at the current sample and will get back to you later. Do you use a vanila 2016 Orbiter or beta?
 

cyph0r

New member
Joined
Feb 10, 2016
Messages
11
Reaction score
2
Points
3
I have this problem as well, but I don't think it is caused by a missing orbiter.lib in the property sheets.
When I use Visual Studio 2013, Atlantis builds just fine (using vanilla Orbiter 2016). When building the same project with VS 2017, I get OP's linker error message.

If I understand the the error message correctly it says that the linker expects a move constructor in the VESSEL2 base class.

Code:
__declspec(dllimport) public: __thiscall VESSEL2::[B]VESSEL2(class VESSEL2 &&[/B])

However, I can only find a copy constructor in orbiter.lib (you can use the DUMPBIN tool to display all exports).

Code:
Version : 0
Machine : 14C (x86)
TimeDateStamp: 57C23433 Sun Aug 28 02:45:39 2016
SizeOfData : 00000024
DLL name : Orbiter.exe
Symbol name : ??0VESSEL2@@QAE@ABV0@@Z (public: __thiscall VESSEL2::[B]VESSEL2(class VESSEL2 const &)[/B])
Type : code
Name type : name
Hint : 48
Name : ??0VESSEL2@@QAE@ABV0@@Z

I suspect this is because the orbiter.lib was compiled using Visual Studio <=2013. Apparently support for implicit move constructors was only added in Visual Studio 2015 (reference).

@OP
You should be able to resolve this by explicitly deleting the move constructor in both Atlantis_SRB and Atlantis_Tank. This prevents the compiler from adding a default constructor that the base class does not support.
Add the following to the class definitions in Atlantis.h

Code:
class SRBFUNC Atlantis_SRB: public VESSEL2 {
public:
	Atlantis_SRB (OBJHANDLE hObj);
	Atlantis_SRB(Atlantis_SRB&&) = delete;  // <- new line
    
[...]

class TANKFUNC Atlantis_Tank: public VESSEL2 {
	friend class Atlantis;

public:
	Atlantis_Tank (OBJHANDLE hObj);
	Atlantis_Tank(Atlantis_Tank&&) = delete;  // <- new line

Or you can just use the VS 2013 toolset instead.
 

chalcrow

Donator
Donator
Joined
Nov 30, 2016
Messages
12
Reaction score
0
Points
0
Hi Face, and cyph0r. I'm using the vanilla Orbiter 2016. I've changed to using VS2017, as the props sheets that Andrew Stokes talks about in his YouTube are for VS2017 (2019 is still new, I'll leave it for now).

cyph0r, your fix works :hailprobe:. Thanks so much for your amazing effort on this. I'll read up on DUMPBIN and copy and move constructors so that I can completely understand.

My interpretation of your fix at present is this:

- This part of the error is indicating that the linker is looking for a move constructor (which I assume is a constructor that is just moving the memory location of an existing class from one place to another?). So there's a constructor which is accepting an existing class of the same type as an argument:

Code:
__declspec(dllimport) public: __thiscall VESSEL2::VESSEL2(class VESSEL2 &&)

And in Atlantis.h, within the declaration of the Atlantis_SRB class we can issue a declaration that deletes the expectation that this move constructor should exist in the VESSEL2 base class - is that correct?

Code:
class SRBFUNC Atlantis_SRB: public VESSEL2 {
public:
	Atlantis_SRB (OBJHANDLE hObj);
	Atlantis_SRB(Atlantis_SRB&&) = delete;  // <- new line

... and then we also do a similar thing in the declaration of the Atlantis_Tank class

Incidentally before I implemented the fix I started again and followed the Andrew Stokes video for the props sheets. This time I added the props sheets to all of the projects in the Atlantis solution (previously I was only adding them to the 'Atlantis' project in the solution, and I configured them all as per the instructions in the video. That did initially fix another issue with an include similar to the problem described here - https://www.orbiter-forum.com/showthread.php?t=7548
 

cyph0r

New member
Joined
Feb 10, 2016
Messages
11
Reaction score
2
Points
3
I am glad you got it to work :cheers:

My interpretation of your fix at present is this:

- This part of the error is indicating that the linker is looking for a move constructor (which I assume is a constructor that is just moving the memory location of an existing class from one place to another?). So there's a constructor which is accepting an existing class of the same type as an argument:

Code:
__declspec(dllimport) public: __thiscall VESSEL2::VESSEL2(class VESSEL2 &&)

And in Atlantis.h, within the declaration of the Atlantis_SRB class we can issue a declaration that deletes the expectation that this move constructor should exist in the VESSEL2 base class - is that correct?

Yes, that is right. These constructors are implicitly generated by the compiler (if not already declared) and are used to initialize an object using another object of the same class. A copy constructor does so by copying the member values, while a move constructor "steals" the memory from the original object without copying anything.
When compiling the project without the explicit delete declarations, the compiler adds a move constructor for Atlantis_SRB and Atlantis_Tank that "calls" respective constructors of the superclass (VESSEL2). Since there is no such constructor for VESSEL2 in the provided binary, linking to the Orbiter API fails.

If you want more information on move constructors you can look here and here.
 

Sbb1413

Well-known member
Joined
Aug 14, 2018
Messages
948
Reaction score
373
Points
78
Location
India
Preferred Pronouns
he/his/him
@Chalcrow, I am using Visual Studio 2017 Express to compile. However, you are an Orbiter Newbie, so fly some fictional gliders, then realistic shuttles before creating/compiling any vessel.
 
Last edited:

Face

Well-known member
Orbiter Contributor
Addon Developer
Beta Tester
Joined
Mar 18, 2008
Messages
4,398
Reaction score
578
Points
153
Location
Vienna
@Chalcrow, I am using Visual Studio 2017 Express to compile. However, you are an Orbiter Newbie, so fly some fictional gliders, then realistic shuttles before creating/compiling any vessel.

So, your solution to the problem is to tell the OP to first fly vessels before even attempting creating them?

I don't understand the logic behind this, because it is not necessary to master flying vessels in order to compile source code. And the OP already described and even demonstrated that he knows a bit about compilers.

Keep in mind that being an Orbiter newbie doesn't necessarily mean to also be a coding newbie.
 

chalcrow

Donator
Donator
Joined
Nov 30, 2016
Messages
12
Reaction score
0
Points
0
Thanks cyph0r, soumya-8974 and Face.

cyph0r thanks for that additional info on the move constructor - very useful thanks.

I've played around with getting Atlantis into orbit a few times before, and I've been studying aspects of rocket science and the physics and mechanics of space flight as well as the practical engineering of real spacecraft over the last 2 years, however I'm sure I know a miniscule amount in relative terms. I also studied advanced mathematical mechanics and physics up to 18-20 years of age but I need to revise. I've started another thread here to get some basic starter device on how to start debugging/developing.

https://www.orbiter-forum.com/showthread.php?p=589325#post589325

Any advice is greatly appreciated!
 

Sbb1413

Well-known member
Joined
Aug 14, 2018
Messages
948
Reaction score
373
Points
78
Location
India
Preferred Pronouns
he/his/him
So, your solution to the problem is to tell the OP to first fly vessels before even attempting creating them?

I don't understand the logic behind this, because it is not necessary to master flying vessels in order to compile the source code. And the OP already described and even demonstrated that he knows a bit about compilers.

Keep in mind that being an Orbiter newbie doesn't necessarily mean to also be a coding newbie.

If he can't fly those vessels, he can't test his own vessels. He will mess up with the throttle, roll, pitch, yaw etc.
 

Face

Well-known member
Orbiter Contributor
Addon Developer
Beta Tester
Joined
Mar 18, 2008
Messages
4,398
Reaction score
578
Points
153
Location
Vienna
Just a heads-up on the compilation problem: I've played with it again and noticed that the changes I had to do in my VS2017 installation to get the stock Atlantis code compiling and debugging are as follows:
  1. Open Atlantis.sln with VS2017, so solution, projects and vsprops get converted. It will not build just now, so close VS again.
  2. Set Orbiter root in newly created \Orbitersdk\resources\orbiterroot.props.
  3. Open solution again and change the property "Platform toolset" to "Visual Studio 2008 (v90)" for all projects.
  4. Change the debug settings of the default project ("Atlantis" for me) to point to the orbiter.exe and the working directory to the Orbiter root directory.
With this, I can set a breakpoint, press F5 ("Start Debugging"), click an Atlantis scenario and see my breakpoint hit.


Unfortunately there is no easy way to get the VS2008 toolset besides installing it, so this might not be the best way for everyone. You can skip the appropriate step and change the code according to cyph0r's excellent explanation, but keep in mind that this build can then have different behavior than the stock module.

---------- Post added at 19:17 ---------- Previous post was at 19:01 ----------

If he can't fly those vessels, he can't test his own vessels. He will mess up with the throttle, roll, pitch, yaw etc.

Sorry, but this is nonsense. The OP's question was about compiling SDK samples, not about how to fly or test vessels.

In addition, you just assume that he will mess up controls on the mere observation that he is an Orbiter newbie. Perhaps he already knows how to control spacecrafts or aircrafts from other simulators or games, or maybe even from reality. Orbiter is not the be-all-end-all when it comes to vehicle simulation.

Please drop the newbie theme, OK?
 
Top