programacion - Biblioteca compartida C++ con plantillas: error de símbolos no definidos
manual de programacion android pdf (4)
Estoy tratando de vincular a una biblioteca compartida con una clase de plantilla, pero me está dando errores de "símbolos indefinidos". He condensado el problema en aproximadamente 20 líneas de código.
shared.h
template <class Type> class myclass {
Type x;
public:
myclass() { x=0; }
void setx(Type y);
Type getx();
};
shared.cpp
#include "shared.h"
template <class Type> void myclass<Type>::setx(Type y) { x = y; }
template <class Type> Type myclass<Type>::getx() { return x; }
main.cpp
#include <iostream>
#include "shared.h"
using namespace std;
int main(int argc, char *argv[]) {
myclass<int> m;
cout << m.getx() << endl;
m.setx(10);
cout << m.getx() << endl;
return 0;
}
Así es como compilo la biblioteca:
g++ -fPIC -c shared.cpp -o shared.o
g++ -dynamiclib -Wl,-dylib_install_name -Wl,libshared.dylib -o libshared.dylib shared.o
Y el programa principal:
g++ -c main.cpp
g++ -o main main.o -L. -lshared
Solo para obtener los siguientes errores:
Undefined symbols:
"myclass<int>::getx()", referenced from:
_main in main.o
_main in main.o
"myclass<int>::setx(int)", referenced from:
_main in main.o
Si shared.h/cpp
el elemento ''plantilla'' en shared.h/cpp
, y lo reemplazo con solo ''int'', todo funciona bien. Además, si solo copio y pego el código de clase de la plantilla directamente en main.cpp
, y no enlazo a la biblioteca compartida, todo funciona también.
¿Cómo puedo obtener una clase de plantilla como esta para trabajar a través de una biblioteca compartida?
Estoy usando MacOS 10.5 con GCC 4.0.1.
Además de las otras respuestas, puede crear instancias explícitas de las clases de plantilla. Esto solo es útil si conoce de antemano qué tipos pueden asumir los parámetros de la plantilla. Crea una instancia de la plantilla con todos estos tipos en la biblioteca.
Para su ejemplo para compilar, solo agregue lo siguiente al final de shared.cpp :
// Instantiate myclass for the supported template type parameters
template class myclass<int>;
template class myclass<long>;
Esto ejemplifica la plantilla con Type = int y coloca el código instanciado en la biblioteca compartida. Agregue tantas instancias explícitas como necesite, para todos los tipos que necesite.
De nuevo, si desea poder instanciar la plantilla con cualquier parámetro de Tipo arbitrario, debe agregar las definiciones al archivo de encabezado, de modo que el compilador conozca el código fuente de la plantilla al crear una instancia en otras unidades de compilación.
El compilador tiene que ver todo el código de una plantilla, por lo que puede generar el código apropiado para el tipo real que desea usar. Por lo tanto, debe colocar todo el código en su .h. archivo.
Las definiciones de funciones de plantilla deben residir en archivos de encabezado. Mueva las definiciones de shared.cpp a shared.h.
Por lo tanto, no puede compilar esto en una biblioteca compartida y luego vincularlo. Simplemente no funciona así.
También debe incluir la implementación de las clases de plantilla en los archivos de encabezado. Esta es una restricción de plantillas en C ++. Por lo tanto, puede incluir shared.cpp desde main (#include) o simplemente mover el código desde shared.cpp en shared.h