2011-03-06 3 views
0

Je travaille sur un système de plugins en C++ où un exécutable C++ charge une DLL et exécute plugin_start (someclass &) via GetProcAddress.C++ Windows Plugins - Passing Classes

Je comprends parfaitement comment passer des pointeurs de fonction au dll, et vice versa, et comment le dll peut utiliser quoi que ce soit défini dans un fichier d'en-tête, mais je voudrais que le dll pour pouvoir utiliser UneClasse où UneClasse est déclaré dans someclass.h MAIS DEFINI dans someclass.cpp. La capture est, someclass est compilé dans l'exécutable appelant qui signifie que lorsque la DLL tente d'appeler une fonction, il obtient une erreur de liaison. Je comprends même pourquoi c'est, ce que je ne comprends pas, c'est comment réaliser ce que je veux. J'imagine que je peux passer un pointeur sur l'objet, et un pointeur vers la fonction, c'est-à-dire someclass * somefunction *, puis l'appeler someclass -> * somefunction() mais cela signifie que je devrais passer un pointeur sur chaque fonctionner dans chaque classe.

Existe-t-il un moyen plus simple de le faire, ou devrais-je m'en tenir uniquement aux fonctions de style C et aux pointeurs de fonction et oublier d'essayer de passer des classes entières entre les deux?

Merci,
Ben

#ifndef EVENTREGISTRAR_H 
#define EVENTREGISTRAR_H 
#include <vector> 

typedef void (__stdcall *error_callback_t)(const char *error); 

class EventRegistrar 
{ 

public: 
    void OnError(error_callback_t fn); 
    void FireError(const char *error); 


private: 
    std::vector<error_callback_t> errors; 

}; 
#endif 

- Cpp

#include "PluginLoader.h" 
void EventRegistrar::OnError(error_callback_t fn) 
{ 
    this->errors.push_back(fn); 
} 

void EventRegistrar::FireError(const char *error) 
{ 
    for (std::vector<error_callback_t>::iterator it = this->errors.begin(); 
     it != this->errors.end(); ++it) 
    { 
     (*it)(error); 
    } 
} 

- DLL

#include "../plugin.h" 
#include <stdio.h> 
void __stdcall error(const char *error) { printf("Error: %s\n",error); } 
extern "C" int __stdcall plugin_start(plugin_start_data& data) 
{ 
    error_callback_t fn = error; 
    data.events.OnError(fn); 
    return LOAD_SUCCESS; 
} 

--error

Error 1 error LNK2001: unresolved external symbol "public: void __thiscall EventRegistrar::OnError(void (__stdcall*)(char const *))" ([email protected]@@[email protected]@Z) D:\Files\C++ Workspace\BLib\BLib\Example Plugin\main.obj Example Plugin 
+0

C'est une mauvaise idée de passer des objets STL à travers les limites de la DLL; séparer l'interface de l'implémentation pour éviter cela. – Luke

Répondre

0

J'ai fait quelque chose comme ça il y a longtemps. J'ai simplement utilisé une interface C droite pour garder les choses simples.

Il y a peut-être un meilleur moyen mais je pense que le passage d'un pointeur sur l'objet est votre approche la meilleure et la plus directe.

+0

Je dois encore passer un pointeur sur les fonctions, correct? J'ai essayé juste de passer un pointeur sur l'objet, data-> events-> OnError (fn); et ont toujours une erreur de lien. – Ben

+0

Non, si le fichier d'en-tête est disponible au moment de la compilation, il suffit de passer un pointeur sur l'objet. Je ne suis pas sûr à 100% de ce que vous faites avec ces événements. Certes, cela compliquerait les choses. Mais référencer un membre de classe à partir d'un pointeur ne doit pas impliquer d'erreur de lien. Cela n'a pas de sens. –

+0

Assez confus. Rendre les membres de EventRegistrar virtuels fait disparaître mon problème et tout fonctionne dandy. – Ben