sintaxis - La variable estática de C++ en.lib no se inicializa
tipos de datos en c++ (2)
Tengo una biblioteca estática (.lib) en VS2010 y estoy vinculándola a mi proyecto de prueba.
La lib tiene una fábrica que creo usando la MACRO siguiente:
#define REGISTER_FACTORY(mType, my_class) /
class Factory##my_class : public CAbstractFactory/
{/
public:/
Factory##my_class() : CAbstractFactory(mType){}/
CBaseClass *Create()/
{ return new my_class(); }/
};/
static Factory##my_class StaticFactory##my_class;
Lo que se supone que sucederá es que en CAbstractFactory la nueva fábrica se registra por mtype
. Pero cuando reviso la fábrica, la fábrica no existe.
Funciona bien cuando uso una DLL en lugar de .lib. Mi suposición es que el enlazador no incluye la variable estática ya que no se referencia o la variable estática ni siquiera se incluyó en la biblioteca.
¿Cómo puedo forzar al enlazador a incluir todos los objetos de la biblioteca estática en mi .exe.
Uso la macro así:
// Register factory that can create CMyObject with ID=100
REGISTER_FACTORY(100, CMyObject);
class CMyObject
{
};
CAbstractFactory se ve así:
class CAbstractFactory {
CAbstractFactory(int id) {
CFactory::instance().add(id, this);
}
}
Luego, en algún otro lugar del código, mi .exe principal que uso:
CBaseClass *pObject = CFactory::instance().Create(100);
Esto le dará a mi un CMyObject
nuevo. La idea es que tengo muchos objetos tipo diferentes y tengo una base de datos que contiene el ID que especifica el tipo de objetos que necesito. 100
es solo un ejemplo.
Así que de hecho, no hago referencia directa a nada de .lib pero quiero poder crear los objetos usando mi fábrica
La clase CFactory es una clase simple que mantiene un registro (en un mapa) de todas las clases de CAbstractFactory y delega el método de creación en la fábrica correcta.
CFactory &CFactory::Instance()
{
static CFactory instance;
return instance;
}
El principal problema radica en el hecho de que no hago referencia a nada desde .lib, ya que todo se hace a través de CFactory. Funciona si lo hago una DLL y me aseguro de agregar alguna referencia a esta DLL para asegurarme de que esté cargada. Pero para una .lib, incluso agregué una función ficticia para asegurarme de tener al menos una referencia que no incluye el resto del código.
static
define un objeto con enlace interno -> si no se usa internamente en la misma unidad de traducción, puede optimizarse. Elimine la static
de su instanciación para que el objeto tenga un enlace externo - Factory##my_class StaticFactory##my_class;
Tuve un problema similar y lo resolví estableciendo el proyecto lib como una dependencia del proyecto de la aplicación principal y luego estableciendo ''Dependencias de la biblioteca de enlaces'' y ''Usar las entradas de dependencia de la biblioteca'' en Sí para el proyecto principal.
Actualizar:
Recientemente descubrí que Visual Studio 2015 ahora es compatible con un /WHOLEARCHIVE
enlazador /WHOLEARCHIVE
. No puedo encontrarlo a través de las opciones del vinculador, pero puede agregarlo como una opción de línea de comando adicional. Funciona de forma similar a la bandera GCC -whole-archive
y lo agrega a sus indicadores de vinculador de destino (no a los indicadores de lib estáticos).
Por ejemplo, especifique /WHOLEARCHIVE:lib_name
como una opción de línea de comando del enlazador adicional e incluirá todos los símbolos de esa lib. Puedes hacer esto más de una lib también.
Si usa this /WHOLEARCHIVE:lib_name
, ya no necesita las ''Dependencias de la Biblioteca de enlaces'' y ''Usar las Entradas de dependencia de la biblioteca'' establecidas en Sí. Esto es perfecto para soluciones generadas a través de CMAKE. Vea una respuesta relacionada aquí: https://.com/a/42083877/1151329