Could you please post your declaration of the OEMUFUNCTION class? Going on what you write, it sounds like there's a fundamental misunderstanding happening somewhere.
Hi Jedidia,Could you please post your declaration of the OEMUFUNCTION class? Going on what you write, it sounds like there's a fundamental misunderstanding happening somewhere.
using std::vector; // added this as only way to make use of vector...
class OEMUFUNCTION /*: public VESSEL*/ {
public:
// constructor / destructor (commented out as has no effect???)
// OEMUFUNCTION();
// ~OEMUFUNCTION();
BOOL EVASelectedCrew ();
// ... a bunch of other functions to call from vessel classes
private:
int maxseats;
int selected;
int numberonship;
// ... a bunch of other private variables (specific for each vessel class instantiating OEMUFUNCTION)
};
#endif
OEMUFUNCTION omeu;
oemu.EVASelectedCrew();
VESSEL *v = oapiGetVesselInterface(/*handle of vessel to interact with*/);
v->SetThrusterGroupLevel(THGROUP_MAIN, 1); // for example...
It means OEMFUNCTION must be a class that publicly inherits from at least VESSEL2. VESSEL4 is the latest, you may as well use that.Hi Blake,
Thank you this makes sense. Does this mean my class can only be interacted with this way if it is instatiated in VESSEL2 calss vessels though?
Congratulations, as I had the impression from your last statements, you have done what I recommended you to do in the first place: You implemented OEMUFUNCTION by composition rather than by inheritance. I.e. the vessel has a member that serves as the interface to your functionality, rather than the vessel incorporating that interface into its own.this is my declaration of OEMUFUNCTION in the .lib project:
Hi Jedidia,Congratulations, as I had the impression from your last statements, you have done what I recommended you to do in the first place: You implemented OEMUFUNCTION by composition rather than by inheritance. I.e. the vessel has a member that serves as the interface to your functionality, rather than the vessel incorporating that interface into its own.
The trouble is, you're still trying to access it as though it was a part of the vessels interface. Which it is not. For that to be the case, and so for the code on the last pages to actually work, OEMUFUNCTION must be a VESSEL2, i.e. must inherit VESSEL2 (or any class that inherits VESSEL2) and must be instantiated by orbiter itself.
Don't bother though, as mentioned this way is better. This way, your vessel is not your OEMUFUNCTION, which keeps things much cleaner. The question now becomes, how can one of your vessels get at the OEMUFUNCTION of another vessel?
You can either do a static global manager where every vessel registers their OEMUFUNCTION instance and others can retrieve it, or you can implement the clbkGeneric method of the vessel to send out the instance when it receives a certain message.
BOOL OEMUFUNCTION::EVASelectedCrew(OBJHANDLE h)
{
VESSEL v* = oapiGetVesselInterfcate(h);
OEMUFUNCTION o*;
v->clbkGeneric(OEMU_MSG, 1, &o);
if (o != NULL) return TRUE;
else return FALSE;
}
ShuttlePB::clbkGeneric (int msg, int additional, void *parameter) // cant remember exact arguments off the top of my head
{
msg = OEMU_MSG;
additional = 1;
parameter = *oemu; // oemu is how I instantiated OEMUFUNCTION in my header (OEMUFUNCTION oemu;)
}
// Define MY_GENERIC_MSG in some header that both ShuttlePB and OEMFUNCTION have access to
int MY_GENERIC_MSG = VMSG_USER + <some number>; // this creates a unique message you will recognize
...
BOOL OEMUFUNCTION::EVASelectedCrew(OBJHANDLE h)
{
VESSEL v* = oapiGetVesselInterface(h); // Get interface to the vessel that has an override for clbkGeneric
v->clbkGeneric(MY_GENERIC_MSG, 1, this); // Call clbkGeneric, passing it a pointer to 'this' instance of OEMFUNCTION.
return true; // not sure what the result here means.
}
ShuttlePB::clbkGeneric (int msg, int additional, void *parameter) // cant remember exact arguments off the top of my head
{
if (msg == MY_GENERIC_MSG) { // Important, so we know that void* parameter is a pointer to OEMUFUNCTION
OEMUFUNCTION* func = (OEMUFUNCTION*)parameter; // Cast parameter to a pointer of OEMUFUNCTION.
func->SomeMethodOnOEMUFUNCTIONClass(); // Make calls on the instance of OEMUFUNCTION passed in the method above.
// note: when this if block exits, you should assume 'func' is no longer valid. Don't try to save it someplace and use it later.
}
}
Hi Blake,C++:...
I have not tested any of this, but I think this is what you are going for. There is nothing special about clbkGeneric, it is just a known method you can implement for any vessel. The msg parameter is intended to help you recognize the caller so that you don't try to use 'parameter' if you don't know what it is pointing to.
It looks like LUA uses clbkGeneric, so if you have a vessel that implements it, and you are not checking 'msg' for your message, that is likely the cause of a CTD.
typedef struct {
char firstname[24];
char lastname[24];
int age;
double weight;
} CREWMEMBER;
CREWMEMBER crew;
// bunch of code etc.
v->clbkGeneric(MY_MESSAGE, 1, &crew);
if (msgid == MY_MESSAGE) {
CREWMEMBER me = (CREWMEMBER&)context;
sprintf (oapiDebugString(), "WEIGHT: %0.2f", me.weight);
}
if (msgid == MY_MESSAGE) {
CREWMEMBER me = (CREWMEMBER*)context;
sprintf (oapiDebugString(), "WEIGHT: %0.2f", me->weight);
}
Hi Blake,C++:if (msgid == MY_MESSAGE) { CREWMEMBER me = (CREWMEMBER*)context; sprintf (oapiDebugString(), "WEIGHT: %0.2f", me->weight); }
Try this change. You are sending the address of your struct, so treat it like a pointer in the clbkGeneric method. That should work.
Hi Blake,
That is what I tried originally, but I can't compile, I get an error "cannot convert from 'CREWMEMBER *' to 'CREWMEMBER '".
CREWMEMBER* me = (CREWMEMBER*)context;
Perfect! I could have sworn that was the first thing I tried!Opps, try this:
C++:CREWMEMBER* me = (CREWMEMBER*)context;
Don't worry about it. This isn't so much related to C++ as these are generic terms from object-oriented programming. You're just learning them by bashing your head against C++, which is a pretty hard way given the utter unhelpfulness of the language, but it's exactly the same way I learned them: By screwing together wild stuff in orbiter with at best half a clue of what I was doing. Now I work as a software developer professionally, so apparently that way of learning does work. Or maybe it's just sheer dumb luck that any of my code ever works. Some days it still feels that way...My apologies for the confusion, this is what you meant by inheritance. Sorry my C++ literacy is not fantastic I wasn't 100% sure what you meant, I would have saved you the trouble.