2

I've had a look through all the similar questions, but this specific scenario doesn't seem to have come up.

I have a plugin system, where the plugin receives the address of a function to call whenever it wants to insert a hook (which is a class function).

plugin:

struct plugin {
...
    bool (*insert_hook)(hook_data*);
...
};

class:

class manager {
...
    private:
        InsertHook(hook_data *hook);
...
};

creation function in manager:

{
    ...
    typedef bool (manager::*InsertHookFunc)(hook_data*);
    InsertHookFunc    hook_func = &manager::InsertHook;

    // assigning this to the plugin ???
    // C2440, cannot convert from 'hook_func' to 'bool (__cdecl *)(hook_data *)'
    plugin->insert_hook = hook_func;
    ...
}

The manager calls into the plugin, and if the plugin needs to insert any hooks, it needs to call into the manager.

What is the correct method for doing it like this? I know it works normally (the plugin is passed a function pointer to the classes creation function to request a plugin object), but it just seems I can't assign it due to it being a class function (using a non-class function, this assignment works fine).

I could create a non-class function as a friend to the manager, but I'm sure this can be done directly, I just can't figure it out...

2
  • Can you use the boost library? Commented Nov 23, 2012 at 5:55
  • boost is unavailable, as it would put dependencies on the plugin design - and the aim is to minimize the amount of work plugins need Commented Nov 23, 2012 at 6:04

3 Answers 3

2

These types need to match:

typedef bool (manager::*InsertHookFunc)(hook_data*);
bool (*insert_hook)(hook_data*);

The direct fix is to insert another manager:: inside plugin:

bool (manager::*insert_hook)(hook_data*);

The best style is probably to move the typedef outside the class manager like this:

struct manager; // allow manager to be referenced without its definition
typedef bool (manager::*InsertHookFunc)(hook_data*);

struct plugin {
...
    InsertHookFunc insert_hook;
...
};

Or if the plugin already sees the definition of manager, just do

    manager::InsertHookFunc insert_hook;

typedef is definitely your friend when dealing with complicated types.

Sign up to request clarification or add additional context in comments.

6 Comments

That would be perfect, only the plugin has no knowledge of the manager :( manager is part of a host executable, which includes the plugin header - the plugin project itself is totally independent, and only has the plugin header available. This is so plugins don't need to be recompiled with manager updates.
Yeah, I thought that might be so… so that's only the third alternative which I added as an afterthought. You don't need a definition of manager to say typedef bool (manager::*InsertHookFunc)(hook_data*); or define or use such a member in plugin. Just use a forward declaration: struct manager; before defining header
the forward declaration works (should have though of that..!), but the plugin still can't call the function as there's still no manager defined - guess I'll have to use a friend function instead. Was worth a try anyway, thanks!
It might be troublesome if the plugin structure is to be used from a non-C++ program.
@ZXcvbnM The plugin would have to be passed a pointer to the manager at runtime. If there's no possibility of multiple managers, then any manager class shouldn't be part of a public interface. Try a namespace instead (for both interface and implementation).
|
0

The function you are trying to use is a non static function of a different class(when it is going to be called), which means to call it you need an instance of the class.

Thus for function pointers to non static member functions to work, you need to pass a pointer to the instance as well.

The definition of the pointer would change to the same as InsertHookFunc You would call it as (ptr->*hook_func )(<insert arg here>)

Alternatively if you make the function(InsertHook) a free friend or a static member, it would work as it is, you would just remove the & in the assignment.

Comments

0

You can't have general function pointers point to non-static member functions like that. It's because all non-static member function have an implicit first argument this. Yes, the this pointer you use in function is actually a hidden argument to the function.

Since you have types such as bool used in your plugin structure, I guess you are only wanting C++ code to be used as plugins. In that case why not simply make the plugin structure an abstract base class that the plugins can inherit?

struct plugin
{
    ...
    virtual bool insert_hook(hook_data*) = 0;
    ...
};

class manager : public plugin
{
public:
    ...
    bool insert_hook(hook_data*) { ... }
    ...
};

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.