2010-12-29 12 views
16

¿Puedo colocar una clase dentro de una DLL? La clase que he escrito es la siguiente:¿Cómo usar una clase en DLL?

class SDLConsole 
{ 
     public: 
      SDLConsole(); 
      ~SDLConsole(){}; 
      void getInfo(int,int); 
      void initConsole(char*, char*, SDL_Surface*, int, int, int); 
      void sendMsg(char*,int, SDL_Surface*); 
      void cls(SDL_Surface*); 

     private: 
       TTF_Font *font; 
       SDL_Surface *consoleImg; 
       int width, pos, height, line, size, ctLine; 
       SDL_Surface* render(char*,int); 

}; 

sé cómo cargar un archivo DLL y utilizar la función dentro de una DLL, pero ¿cómo puedo poner una clase dentro de un archivo DLL? Muchas gracias.

+0

Creo que todo lo que necesita es [aquí] (http://msdn.microsoft.com/en-us/library/a90k134d.aspx) – icecrime

+0

¿Lo ha intentado? – BlackBear

Respuesta

20

Si usa el enlace dinámico en tiempo de ejecución (usa LoadLibrary para cargar el dll) no puede acceder directamente a la clase, necesita declarar una interfaz para su clase y crear una función que devuelva una instancia de esta clase, como esta:

class ISDLConsole 
{ 
    public:    
     virtual void getInfo(int,int) = 0; 
     virtual void initConsole(char*, char*, SDL_Surface*, int, int, int) = 0; 
     virtual void sendMsg(char*,int, SDL_Surface*) = 0; 
     virtual void cls(SDL_Surface*) = 0; 
}; 

class SDLConsole: public ISDLConsole 
{ 
    //rest of the code 
}; 

__declspec(dllexport) ISDLConsole *Create() 
{ 
    return new SDLConsole(); 
} 

de lo contrario, si se vincula la DLL durante el tiempo de carga, sólo tiene que utilizar la información proporcionada por icecrime: http://msdn.microsoft.com/en-us/library/a90k134d.aspx

+0

De esta manera es mucho más robusto que '__declspec (dllexport)'. Incluso el enlace de tiempo de carga debería usar este método. –

+0

@Ben: ¿por qué es más robusto? –

+5

Porque solo el diseño de la tabla v debe coincidir entre la biblioteca y el cliente, lo cual es relativamente fácil de lograr, incluso entre diferentes idiomas.Por otro lado, con '__declspec (dllexport)' todo tiene que coincidir: proveedor del compilador, versión del compilador, opciones de compilación, o terminará con una falta de concordancia de nombres (error de enlace) o una violación de una regla de definición y choques correspondientes. –

4

usted puede, y toda la información que necesita están en this page y this page:

#ifdef _EXPORTING 
    #define CLASS_DECLSPEC __declspec(dllexport) 
#else 
    #define CLASS_DECLSPEC __declspec(dllimport) 
#endif 

class CLASS_DECLSPEC SDLConsole 
{ 
    /* ... */ 
}; 

Todo lo que queda es definir el símbolo del preprocesador _EXPORTING al compilar la DLL.

+2

Eso no es "todo lo que queda". También debe asegurarse de que se utiliza el mismo compilador exacto para compilar el archivo DLL y todos los clientes, que las opciones del compilador también coinciden. Usted paga una gran penalización de mantenimiento por hacer las cosas de esta manera, la [interfaz virtual pura según lo sugerido por bcsanches] (http://stackoverflow.com/questions/4555961/how-to-use-a-class-in-dll/4556025 # 4556025) es mucho mejor. –

+0

@Ben: probablemente tengas razón, pero tengo que admitir que siempre he hecho las cosas de esta manera y que simplemente no puedo imaginar usar el método de 'interfaz virtual pura' en un gran proyecto – icecrime

+0

Si tienes módulos que son estrechamente acoplados porque todos son locales para un solo proyecto, ¿por qué no usar solo bibliotecas estáticas? –

12

Solution sugerido por bcsanches,

__declspec(dllexport) ISDLConsole *Create() 
{ 
    return new SDLConsole(); 
} 

Si usted va a utilizar este enfoque como suggested por bcsanches, a continuación, asegúrese de que utiliza la siguiente función para delete su objeto,

__declspec(dllexport) void Destroy(ISDLConsole *instance) 
{ 
     delete instance; 
} 

Definir tales funciones siempre in par, ya que garantiza que elimine sus objetos del mismo heap/memory-pool/etc en el que se crearon. Consulte esto pair-functions

+0

Quiero crear una DLL de mi clase de C++ y usar esa DLL en mi aplicación de C#. ¿Puedes guiarme en eso también? ¿Qué más se necesita? ¿Cómo puedo llamar mi dll en C# cuando lo creo de esta manera? – Breeze

+1

@Hossein: busque pinvoke en C#. Encontrará muchos temas sobre eso. – Nawaz

+0

quieres decir que necesito usar el DIIIMport convencional al igual que dlls normales (como user32.dll)? vale, lo intentaré – Breeze

2

Si desea exponer los datos en una clase, las soluciones anteriores no lo cortarán. Debe presionar __declspec(dllexport) en la clase misma en la compilación de la DLL y __declspec(dllimport) en el módulo que enlaza con la DLL.

Una técnica común es hacer esto (asistentes de Microsoft producen código como este):

#ifdef EXPORT_API 
#define MY_API __declspec(dllexport) 
#else 
#define MY_API __declspec(dllimport) 
#endif 

class MY_API MyClass { 
    ... 
}; 

A continuación, asegúrese EXPORT_API se define en el proyecto de DLL, y asegúrese de que no está definido en el módulo que enlaces a la DLL.

Si crea desde cero un nuevo proyecto DLL en Visual C++ y marca la casilla de verificación "Exportar símbolos", se generará código de ejemplo con esta técnica.

Cuestiones relacionadas