C++ Question making a globalc clbk (function pointer) local...

fred18

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

I'm facing a difficult issue that I can't find a way to solve.

In the Orbiter APIs there are some defined function pointers as clbks that can be used. The first one I'm using is the LoadMeshClbkFunc used by oapiLoadMeshGlobal which is defined like this in OrbiterAPI.h

Code:
typedef void (*LoadMeshClbkFunc)(MESHHANDLE hMesh, bool firstload);

if I then define a GLOBAL function like

Code:
void MyLoadMeshClbk(MESHHANDLE hMesh,bool firstload){
//do something
return;

and then I call it when I load the mesh with
Code:
oapiLoadMeshGlobal("meshname",MyLoadMeshClbk);

it works... BUT

That is a GLOBAL function that means that I cannot pass vessel specific parameters to it. for example I can't get it to do different things if D3D9 is active or not because it does not get the class variables that defines it.

Now, I'm finding some workarounds but they are not very clean, and I will face this issue some other times during development. I would need to make oapiLoadMeshGlobal to accept MyLoadMeshClbk as a class function and not a global function, but if I define it in my class the oapiLoadMeshGlobal throws an error and does not compile because types are different etc etc

If I use a global pointer to my vessel it then means that if I have multiple vessel instances in the scenario things gets messed up quickly.

So, does anyone know how to make the global clbk function somehow accepted even if it's a local class one?

Or to pass the right pointer to the clbk so i will have the right results, it doesn't make much difference

I hope I was clear enogh, thanks in advance!
 
Last edited:

kuddel

Donator
Donator
Joined
Apr 1, 2008
Messages
2,064
Reaction score
507
Points
113
The callback function doesn't have to be global, it just can't be a member function (aka method) of an object.
A static member however would work.
Nevertheless that would possibly not get you any further because you would like to have access to the 'this' pointer.

Think of the difference between a static and a non-static member like this:
Whenever a member-function is called, the C++ compiler automatically adds the 'this' pointer to the call-stack (as the 1st parameter e.g.)
Any static member call does not have an object "it belongs" to, so no 'this' pointer here.

If you are sure that you only have one instance of your object, you could either implement a singleton pattern (anti-pattern ;) ) or store only the single object reference, so you can access the instance from the static context.

PHP:
class MyClass {
public:
  MyClass() { if (!pInstance) pInstance = this; }
  ~MyClass() { if(pInstance==this) pInstance = NULL; }

  static *MyClass pInstance;
  static void callback (MESHHANDLE hMesh, bool firstload) {
    // pInstance could be NULL, so check ;)
    if (pInstance) pInstance->memberFunction(hMesh, firstload);
  }
private:
  void memberFunction (MESHHANDLE hMesh, bool firstload) {
    // do whatever, cause 'this' is valid here
    this->foo();
  }
  void foo () {}
}
MyClass::pInstance(NULL);
Note, that this is untested code, just typed in to show the idea

When you have multiple instances however, you must think of something more complicated ;) like a lookup table based on MESHHANDLE as key e.g.
but I doubt that this fits your idea of "clean" ;)


A nice read on this might be here: http://www.newty.de/fpt/callback.html
 
Last edited:

fred18

Addon Developer
Addon Developer
Donator
Joined
Feb 2, 2012
Messages
1,667
Reaction score
104
Points
78
Wow, thank you very much for your explanation kuddel!

The static part was not completely known to me so this is a very interesting part I am learning. Unfortunately this is not enough, since, as you guessed, I'm going to need numerous instances of the class, so I would need to make up something "dirty" for that. It is a vessel, like a SC3 vessel, so there could be hundreds of them in the sim... thank you anyway!
 
Top