usos que puede programas programar programa con aplicaciones c++ windows dll

c++ - que - programas en c



¿Cómo construyo una DLL agnóstico de la versión en tiempo de ejecución en C++? (8)

Mi producto es una biblioteca C ++ que, en Windows, se distribuye como dll. Hace muy poco uso del c-runtime (iostream básico y eso es todo), así que estoy seguro de que todas las versiones recientes de CRT estarán bien.

Como se supone que mi cliente construirá su aplicación usando mi dll, no quiero imponerle ninguna versión de tiempo de ejecución específica. Me gustaría que mi dll se vincule a la versión de la biblioteca de tiempo de ejecución que esté usando la aplicación de mi cliente (y puedo suponer que utilizará enlaces dinámicos para su CRT). Después de todo, ¿no es eso de lo que se trata la vinculación dinámica? ¿Es eso posible?

EDITAR: vincular el dll con las bibliotecas libs del tiempo de ejecución estático tampoco funcionará, porque entonces el tiempo de ejecución estático (del dll) y el tiempo de ejecución dinámico (de la aplicación del cliente) se mezclarán, lo cual es malo.

EDITAR: Lo que principalmente estoy preguntando es ¿cómo le digo al cargador de tiempo de ejecución que vincule mi dll con el CRT con el que está vinculada la aplicación? Algo con el manifiesto, tal vez? En términos más generales, mi pregunta es cómo construir un dll que se comporte bien, que los clientes deben usar para construir sus propias aplicaciones.

EDITAR: gracias a los consejos en las respuestas, he transferido todas las referencias a clases std en funciones en línea en mis encabezados, y vinculé mi dll con las bibliotecas de tiempo de ejecución estáticas. Ahora parece funcionar incluso en aplicaciones vinculadas con diferentes versiones de CRT.


Puede lograr esto utilizando llamadas de WinAPI para E / S y cualquier otra cosa que posiblemente dependa del tiempo de ejecución.

La parte más dolorosa es que puede tener que anular el new global y delete para usar las funciones de WinAPI exclusivamente porque es probable que usen malloc / free internamente. Hay muchos otros aspectos dolorosos en esto, y mi opinión es que no vale la pena. Aquí hay un artículo que cubre este tema.


Si expone cualquier objeto C ++ a través de los límites de la DLL, esto simplemente no es posible. Lo que puede hacer (y usamos una DLL de terceros que hace esto) es crear su biblioteca en múltiples configuraciones (32 bits / 64 bits, depurar / liberar, tiempo de ejecución estático / dinámico, biblioteca estática / dinámica) para satisfacer como muchas personas como sea posible. Esto puede ser un poco tedioso de configurar al principio, pero una vez que tenga todas las configuraciones configuradas, solo es cuestión de construirlas todas. Por supuesto, también debe considerar qué tiempo de ejecución está compilando (vc8, vc9, vc10, etc.), por lo que si desea cubrir todas las bases, puede tener bastantes configuraciones.


Si quieres exponer tus objetos en tiempo de ejecución neutral, entonces no veo otra solución que no sea COM.


Su dll está vinculado contra el c-runtime con el que se compiló. Tu aplicación siempre usará este tiempo de ejecución. Cualquier persona que enlace a tu dll usa su c-runtime. Entonces no habrá ningún problema con esto.


Vincular su DLL con las bibliotecas de tiempo de ejecución estáticas debería funcionar, excepto que debe tener mucho cuidado con la administración de memoria (por ejemplo, quien llama a su DLL no puede liberar () o eliminar [] nada asignado por su DLL) y no puede intercambiar datos C estándar estructuras (por ejemplo, ARCHIVO *). (¿Me estoy perdiendo algo?)


Bueno, hay una gran diferencia entre el C-runtime y el C ++ - runtime. Si usa msvcrt.dll, que en los últimos años se convirtió en "caballero" como una verdadera DLL de sistema, podría confiar en su existencia en XP en adelante (aunque para Windows 2000 necesitaría algún redistribuible para la versión 6 de msvcrt.dll). ) Puede hacer uso de msvcrt.dll compilando su código con el compilador de los últimos WDK (kits de controladores de Windows). Aunque este es el código de modo de usuario, este es un método viable y bueno para compilarlo.

IOStreams, sin embargo, requiere C ++ - runtime. Y eso complica mucho las cosas.

EDITAR: vincular el dll con las bibliotecas libs del tiempo de ejecución estático tampoco funcionará, porque entonces el tiempo de ejecución estático (del dll) y el tiempo de ejecución dinámico (de la aplicación del cliente) se mezclarán, lo cual es malo.

Bueno, si mezclas el código de esa manera, tienes algo mal en tu diseño. Tendría problemas similares al ejecutar una compilación de depuración de su DLL con una compilación de lanzamiento del otro código o viceversa.

Solo puedo recomendar que haga uso directo de COM o, si es demasiado grande, trate de emular algunas ideas de COM. El más importante sería que tiene una función de fábrica y que hay una interfaz (de clase) declarada (y nunca cambia) entre esas dos partes de código (es decir, la DLL y su llamador). La función de fábrica devolvería una instancia de la clase y la clase gestionaría su propia duración (lo que implica que todo el código para la asignación y desasignación residiría en la misma entidad, es decir, su DLL). La administración de por vida estaría expuesta a través de addref y release funciones de miembros. IUnknown podría ser la base de esta interfaz tuya sin depender de otras partes del COM real.

EDITAR: Lo que principalmente estoy preguntando es ¿cómo le digo al cargador de tiempo de ejecución que vincule mi dll con el CRT con el que está vinculada la aplicación? Algo con el manifiesto, tal vez? De manera más general, mi pregunta es cómo construir un dll que se comporte bien, que los clientes deben usar para construir sus propias aplicaciones.

No es nada fácil. Incluso si tuviera todas las versiones de VS instaladas, tendría que crear un script para salir de este dilema y elegir la versión correcta.


No hay una manera real de garantizar que su DLL funcione con múltiples tiempos de ejecución: cualquiera de los tipos que cambian entre ellos puede generar incompatibilidades. Por ejemplo, el tamaño de un objeto puede cambiar, o la ubicación de los miembros en ellos. Hay muy poco espacio en C ++ para este tipo de cosas.

Lo mejor que puede hacer es vincular estáticamente al tiempo de ejecución y asegurarse de que la API exportada esté limitada a los tipos estrictamente bajo su control, sin pasar std::string por una función, no stdlib como miembros y no como new en uno. DLL y delete en otro. No mezcle funciones en línea y exportadas (incluidos constructores / destructores) para el mismo objeto, ya que el orden y el relleno de los miembros pueden cambiar entre los compiladores. El idioma pimpl podría ayudar aquí.


Si usa C ++, parece imposible cruzar los límites de tiempo de ejecución a menos que se limite a lo que puede exponerse. Como se mencionó anteriormente, std :: objects no funciona (std :: string, por ejemplo).

Aquí hay un pequeño ejemplo que causará un bloqueo:

clase Base
{
público:
virtual ~ Base ()
{
}
};

clase ClassInDll: base pública
{public: __declspec (dllexport) ClassInDll (int arg);
__declspec (dllexport) ~ ClassInDll ();

privado: int _arg;
};

Si esta clase se compila en una DLL de modo de lanzamiento VS2008 y se genera un .exe en modo de depuración VS2008, haga lo siguiente:

ClassInDll * c = new ClassInDll (1); eliminar c;

la instrucción "delete c" causa un bloqueo. Tiene que ver con el hecho de que ClassInDll tiene un destructor virtual.