C++ Question class, plugin and MFD

fred18

Addon Developer
Addon Developer
Donator
Joined
Feb 2, 2012
Messages
1,667
Reaction score
115
Points
78
Hi all,

here I am starting to ask questions again to those who know much better programming than me... :embarrassed:

The question is quite simple, and it's been debated somehow on the forum, I spent sometimes reading about it, but it's either too complicated or not what I'm looking for so here it is:

I have a class that handles a series of variables and routines, a plugin that creates an instance of that class in the simulation and I want an MFD to access the data contained in that class. How can I do it?

In MS2015 I used the dynamic cast and worked perfectly but that was a vessel class, I had much more access (like handle, interface etc) than to a generic class I created with a plugin.

Can anyone please help?

:cheers:
 
Hi Fred,

Provided your plugin's pointer is declared in one file, you can declare the plugin's pointer as external global variable in the MFD constructor source file, and store it in the MFD by using the MFDs constructor. See here:
https://sourceforge.net/p/enjomitchsorbit/codeHG/ci/default/tree/launchmfd/LaunchMFD.cpp#l72

Here, I add some additional purism, because I pass the global variable to the MFDs constructor, instead of just using it there:
https://sourceforge.net/p/enjomitchsorbit/codeHG/ci/default/tree/launchmfd/LaunchMFD.cpp#l354

Then you can access the plugin's members from within the MFD.

Go ahead, if you need more clarifications.
 
I have a class that handles a series of variables and routines, a plugin that creates an instance of that class in the simulation and I want an MFD to access the data contained in that class. How can I do it?

This is too vague to give an answer IMHO. Could you elaborate on your specific use-case?

Do you talk about components of one single addon, where the author has everything in his own hands, or do you talk about an open system that should offer a kind of SDK like e.g. Dan's OrbiterSound?

Is the data layout fixed, or should it be easily extendable?

What is the DLL granularity you have in mind? MFD.dll, vessel.dll, data.dll, with the later being some kind of manager? Or more like MFD.dll and vessel.dll only, with the data stored on the vessel side?

Is the data very dynamic, or is it more like some description that gets defined on design-time, then never changes?

Answering these question would help to get a better understanding of what you are talking about.
 
Thank you! I'll give it a try! In my ignoranceI didn't even know that you could change the constructor's parameters in a derived class :facepalm:
 
I didn't even know that you could change the constructor's parameters in a derived class
It's a common technique for parameterizing or "configuring" a derived class, which might be derived from an interface with no constructor parameters at all. You have to inject the derived class' dependencies somehow [EDIT], which may be different for various concrete derived classes[/EDIT], still adhering to the interface limitations it has - I specifically mean, that the derived class cannot change parameters of the common virtual method of the interface.
 
Last edited:
Well, first of all thank you for being ready for the replies.

I'm trying what Enjo suggested since it could be very useful to learn.

In the meantime from the questions of Face I realized that it might not be needed, since the application I'm building consists of both an MFD and a plugin that must be there together, so basically I can build up a single dll that does everything for both sides instead of becoming crazy in passing information across different dlls...

anyway I'll answer to face's question in order to give the big picture. I'm working on the new space network plugin and the idea is to have the plugin with a dialog that holds the "ground receiving and transmitting network" and the MFD mode that holds the Vessel receing and transmitting network.
The process of radio signals around in the sim is done by a class that is created globally.

Now, I was thinking of having two different projects, so two different dlls, one for the plugin and one for the mfd but it could be not needed.

Do you talk about components of one single addon, where the author has everything in his own hands, or do you talk about an open system that should offer a kind of SDK like e.g. Dan's OrbiterSound?
everything in my hands

Is the data layout fixed, or should it be easily extendable?
fixed

What is the DLL granularity you have in mind? MFD.dll, vessel.dll, data.dll, with the later being some kind of manager? Or more like MFD.dll and vessel.dll only, with the data stored on the vessel side?
it's not vessel.dll, it's plugin.dll (dialog), but it's explained above hopefully more clear

Is the data very dynamic, or is it more like some description that gets defined on design-time, then never changes?
it's basically text and numbers structured and "transmitted"
 
In the meantime from the questions of Face I realized that it might not be needed, since the application I'm building consists of both an MFD and a plugin that must be there together, so basically I can build up a single dll that does everything for both sides instead of becoming crazy in passing information across different dlls...

Indeed I think it would minimize complexity to just stick with one DLL in that use-case.

You could store the single SpaceNetworkManager instance in a global static variable, then access it from all the MFD mode instances to e.g. SendMessage user input. If you plan receiving via MFD, too, you could just opt for a polling approach in the Update() method of the MFD modes, where you give the manager your linked vessel, and it returns the next string that should be displayed.

Using frameworks or pointer casting inside a single DLL to pass messages around would be overkill IMHO. What's next, Orbiter MVVM Dependency Injection Framework? :lol:
 
What's next, Orbiter MVVM Dependency Injection Framework? :lol:
No, Spaghetti Code.

There's no reason to be ashamed of (or to laugh from), when somebody wants to learn software engineering. All of my Orbiter libraries (not Dependency Injection Frameworks) are results of hours of decoupling and separation of concepts. A relevant counter example is Fred's Multistage PEG. I've tried to incorporate it into Launch MFD, but it's so tightly coupled with Vessel class that I decided not to break my neck on it.
No offense, Fred. I didn't want to bring it out until now. Keep learning and asking questions :tiphat:
 
Relevant to PEG I've been thinking a lot that since now I've learned how to deal with difference classes, I should make it a separate class, so I can easily reuse it in other future addons. I'll do it and pass it to you the moment it is done!
 
There's no reason to be ashamed of (or to laugh from), when somebody wants to learn software engineering. All of my Orbiter libraries (not Dependency Injection Frameworks) are results of hours of decoupling and separation of concepts. A relevant counter example is Fred's Multistage PEG. I've tried to incorporate it into Launch MFD, but it's so tightly coupled with Vessel class that I decided not to break my neck on it.
No offense, Fred. I didn't want to bring it out until now. Keep learning and asking questions :tiphat:

Unfortunately, many people that call themselves software engineers miss an important point: the goal they want to achieve with their work. Most are so entangled in the way they want to work, in the patterns they want to apply, in the possible combinations their components might enable, that they don't see that all those frameworks, decoupling, and separation of concepts just make their work more complex and complicated to use. Up to a point where the very reasons that got the work started can't be fulfilled anymore. There is even a word for that: architecture astronauts. Somewhat fitting in Orbiter's environment, isn't it? :rofl:

That's why I often try to understand what people actually want to do before I give an answer to such questions. I think knowing what you want to do, reflecting on it, and then choosing the best tool to achieve it is a good way to learn software engineering, if not even engineering in general.

Unfortunately there is this frustrating trend in CS to chase buzzwords instead of sticking with KISS. This is what my statement meant to address in good humor. I'm sorry if you mistook that for criticism of your work, it was not meant that way.

And of course you are right that nobody should be laughed at for trying to learn. Nobody here did that to Fred, though.
 
I agree with your point. Notice however that principles like Single Responsibility or Loose Coupling are entry points to both paths: either software engineering or architecture astronaut, the latter of whom choose the simpler path of just impressing their bosses with buzzwords, to rationalize their (unfairly) higher salary.

Regarding the first path, I don't know how you plan your architecture, but for me it's much much easier to think of any plan, once my classes are small (SRP). Only then I'm able to creatively combine them into a higher hierarchy. Loose Coupling helps in extracting commonly used code into independent libraries and allows hassle free unit testing.

So... it's not a good idea to associate Object Oriented Design with only the second path.
 
Notice however that principles like Single Responsibility or Loose Coupling are entry points to both paths

Indeed. Using SOLID principles to get on your way is a good idea. However, the principles as such should not be taken as dogma.

Regarding the first path, I don't know how you plan your architecture, but for me it's much much easier to think of any plan, once my classes are small (SRP).

To be honest, I don't plan architectures (anymore). I start with a concept, then I check which parts in this concept could be achieved with what tools. Object Oriented Design (or Programming) is just one of the available tools.

The architecture most of the time comes naturally. It is often a convergence of thoughts starting from different aspects. Form follows function, so to say.

So... it's not a good idea to associate Object Oriented Design with only the second path.

Of course not. It is just as much a valid engineering method as Functional Design or straight out batch scripting IMHO. But you can over-do it just like the other methods, as well.
 
Using frameworks or pointer casting inside a single DLL to pass messages around would be overkill IMHO. What's next, Orbiter MVVM Dependency Injection Framework? :lol:

AOP for Orbiter of course. That is the real deal. :lol:

---------- Post added at 12:00 PM ---------- Previous post was at 11:54 AM ----------

The architecture most of the time comes naturally. It is often a convergence of thoughts starting from different aspects. Form follows function, so to say.

Well, I see it a bit different (call me antique there), but I see the architecture as the "values" of the program. Its not so much about which layer in a hierarchy or about which package must be where... but what non-functional or abstract concept you think is important when having multiple solutions to choose from. Like "Must the program be robust?" Or "Its as fast as possible." Or "I can still read my code next year."

Some decisions must be made early and those decisions are in the end pretty final. It makes no sense switching programming language or framework later. But if you have done all the rest properly to SOLID, its no problem to take the features of your program and move them into a new framework. Or at least keep the algorithms in a new programming language (though this makes no sense. If you program Java like you program C++, the result is terribly slow and buggy. And the other way around as well).

But back to topic: Architecture must live and must change of course... but much slower than the rest of your program.

And if you have a system made of multiple programs or multiple orbiter vessels, you should of course change your architecture at geological speeds, or you would open Pandoras box. :lol:
 
AOP for Orbiter of course. That is the real deal.

I hope you mean Aspect Oriented Programming, otherwise I just demonstrated my ignorance of yet another TLA in the buzzword pool :D .
 
I just rejump in the topic to say that I very agree that too often the result is even different from the target of the beginning and it happened always to me, but for a slight different reason in my case: I haven't studied coding or anything, I "learned" c++ (if learned can be used) starting from artlav sc3->c++ converter, so during this years it has always been learning by doing, so I was discovering what I could do and how I could do better while doing it, and at the end of every project I made, I would have gone back and rewrite it from scratch with the knowledge gained in the meantime.

That's what I'm trying to do differently with the new space network plugin, to fix stuff mostly at the beginning in order to have a clear and optimal implementation.

not easy, but this time I want to try it :yes:
 
I hope you mean Aspect Oriented Programming, otherwise I just demonstrated my ignorance of yet another TLA in the buzzword pool :D .

Of course :lol:

If you use AOP properly, its a great tool for developing enterprise software. If you use it wrong, its the best way to make your code perfectly unreadable and can cause very dramatic crashes. :lol:
 
That's what I'm trying to do differently with the new space network plugin, to fix stuff mostly at the beginning in order to have a clear and optimal implementation.

not easy, but this time I want to try it :yes:
It always returns. I'm sometimes angry on myself for the style in which I develop some system of mine. But when I run it, it evaluates 10 years of data on multiple cores in a matter of 2 seconds. All thanks to the initially limiting purism I torment myself with :)
 
So... since I agree with you guys, and I'm still planning, getting back to the topic here's a couple of new linked questions:

Space Network plugin will create a global class which will handle radio signals around the sim. Together with the plugin and its dialog there will be an MFD so each vessel will be able to interact.

The idea, as mentioned, is anyway to create a sort of SDK so radio messages can also be programmed and used by developers.

Question is: how can I access from a different dll (like a vessel) to a global class? as I was mentioning before I should use dynamic cast right? if the global class was a vessel I'd use get handle by name and get interface, but how can I do it with a class I created myself?

Another very silly question (:blush:) is: I wanted to make the code of the MFD in a different cpp file, but since the global class that handles the process is defined in the dialog plugin cpp file I can't access it from the MFD cpp. I solved it putting all the MFD code underneath the plugin. I also noticed that including (#include) the plugin file in the MFD doesn't do the trick because the global class isn't recognised anyway... How can I access the global class simply from another cpp file?
 
Question is: how can I access from a different dll (like a vessel) to a global class? as I was mentioning before I should use dynamic cast right? if the global class was a vessel I'd use get handle by name and get interface, but how can I do it with a class I created myself?

Well, hlynkacg sort of asked the same question here: http://www.orbiter-forum.com/showthread.php?t=37678
My last post there contains a full example of such a constellation and a possible solution. However, here is the point where frameworks like ModuleMessaging can help you.

Another very silly question (:blush:) is: I wanted to make the code of the MFD in a different cpp file, but since the global class that handles the process is defined in the dialog plugin cpp file I can't access it from the MFD cpp. I solved it putting all the MFD code underneath the plugin. I also noticed that including (#include) the plugin file in the MFD doesn't do the trick because the global class isn't recognised anyway... How can I access the global class simply from another cpp file?

I assume you mean a global variable. You need to tell the compiler that the declaration in the second cpp is just a reference to the real variable, and let the linker solve it when all objects are put together.
Let's say you have the dialog.cpp with a SpaceNetworkManager g_SpaceNetworkManager declaration in it. Then simply put an extern SpaceNetworkManager g_SpaceNetworkManager declaration into the MFD.cpp. This site here explains it a bit better: http://www.learncpp.com/cpp-tutorial/42-global-variables/
 
Back
Top