¿Qué hace que un programa (en un lenguaje como C ++) sea multiplataforma o no?

8

Tengo una experiencia de programación bastante básica con Java y he probado C ++ y Python. Si bien tiene sentido para Java, los programas básicos que he escrito en C ++ se han ejecutado bien en Windows y OS X. He podido enviar el archivo fuente a la otra computadora, compilarlo y ejecutarlo. Los programas son bastante básicos, principalmente solo cosas básicas orientadas a objetos que he estado haciendo para tratar de aprender C ++.

Obviamente, sin embargo, no puede compilar cualquier programa C ++ en cualquier máquina y hacer que funcione bien. ¿En qué punto sucede eso? ¿A qué nivel de complejidad la plataforma comienza a importar y el programa no se ejecutará en cualquier lugar? ¿Es cuando usas bibliotecas específicas de la plataforma? ¿Podría un programa hacerse multiplataforma en C ++ simplemente usando bibliotecas multiplataforma?

He estado tratando de resolver esto por mi cuenta, pero todo lo que he encontrado pasa por alto o simplemente no responde a la pregunta, gran parte de lo que surge son emuladores o personas que preguntan qué idiomas son multiplataforma.

Chris
fuente
2
Las bibliotecas específicas de la plataforma, las extensiones de compilador no estándar, cualquier dependencia de cómo los bits se disponen realmente en la memoria y cualquier otra forma de comportamiento indefinido / no especificado son las razones típicas que conozco para que el código se convierta en una plataforma específica. Si evita todo eso, sí, C ++ es bastante portátil por defecto.
Ixrec
"¿Podría un programa hacerse multiplataforma en C ++ simplemente usando bibliotecas multiplataforma?" Esto es mayormente cierto. También necesita compilar (hacer los binarios) para cada plataforma porque el código de máquina compilado es específico de la arquitectura.
rwong
1
Puede usar marcos Qt o POCO .
Basile Starynkevitch

Respuestas:

6

Hay una línea muy clara en la arena entre la plataforma cruzada y la plataforma única:

¿Utiliza un programa solo las API expuestas por la Biblioteca estándar en la que está construido?

Si apunta a una implementación estándar, cualquier plataforma que implemente ese estándar debería, en teoría, compilar y ejecutar su programa correctamente. Hay muchas excepciones, pero en general, si evita los trucos ingeniosos, debería poder evitar muchas de esas excepciones.

La razón por la cual este problema surge específicamente con C ++ es que, durante mucho tiempo, la Biblioteca estándar de C ++ no incluyó muchos módulos que sean útiles para programas no triviales. La concurrencia y la GUI son las dos grandes. Esto significaba que un programa creado utilizando solo la Biblioteca estándar de C ++ no podía tener muchas de las características que esperamos del software moderno.

¿Cómo escribimos software multiplataforma que hace cosas que la Biblioteca estándar no admite?

Usted menciona "bibliotecas multiplataforma", que en la práctica normalmente se denominan "marcos" o "kits de herramientas" en función de su alcance. La forma de escribir software en C ++ que sea multiplataforma es apuntar no solo a la Biblioteca estándar, sino a un marco que se basa en las plataformas de destino.

Esencialmente, terminas externalizando los bits específicos de la plataforma a otra biblioteca. Por ejemplo, wxWidgets es un marco popular. Puede usar sus clases para construir una GUI y funcionalidad relacionada (por ejemplo, cuadros de diálogo estándar para seleccionar archivos). Debajo de las cubiertas, utiliza compilación condicional para implementar la GUI usando la GUI nativa para cada plataforma. Pero como usuario de la biblioteca, nada de eso le importa.


Nota histórica: aquí en 2015 los compiladores y bibliotecas de C ++ son, en su mayor parte, realmente buenos. Regresar unos años, y eso no es cierto. C ++ no tenía un estándar oficial hasta 1998, muchos años después de su inicio. A los proveedores les llevó mucho tiempo actualizar sus compiladores y bibliotecas para implementar el estándar correctamente. Las extensiones específicas del proveedor abundaban (y todavía existen, en realidad). Algunos compiladores tenían encabezados y funcionalidad no estándar. La portabilidad del código era prácticamente inexistente. La reputación de C ++ en términos de portabilidad aún sufre.


fuente
5

¿A qué nivel de complejidad la plataforma comienza a importar y el programa no se ejecutará en cualquier lugar?

Básicamente cualquier cosa no trivial. Si escribe un programa no trivial, lo hará acabar accidentalmente en función de una manera compilador específico que éste ordene sobrecargas, mira hacia arriba, nombres y otras cosas complejas. Además, prácticamente todos los programas no triviales dependen del comportamiento específico de la plataforma no estándar porque el estándar realmente no proporciona nada excepto unos pocos contenedores.

Sin embargo, los programas no triviales pueden variar ampliamente en la facilidad con que se transfieren a otra plataforma. Si lo programó bien y se atuvo a las reglas, puede transferirlo con bastante facilidad y obtener bonificación si puede abstraer las piezas en una biblioteca (que ya se le ha proporcionado, por ejemplo, Boost.Filesystem).

Los programas en su mayoría solo se vuelven muy difíciles de transportar entre plataformas si realizan tareas inherentemente específicas de la plataforma, por ejemplo, escribir datos en el disco con ciertas garantías de atomicidad / consistencia, o, si era un imbécil y hacía cosas estúpidas que eran nunca lo que deberías haber hecho en primer lugar, como lanzar entre ints y punteros.

DeadMG
fuente
2
¿Seguramente esto exagera el caso? Sé que un código C ++ más esotérico puede encontrarse con varios errores de compilación en compiladores más antiguos o de menor calidad, pero cualquier compilador razonablemente compatible con los estándares debería manejar cosas como la sobrecarga y la búsqueda de nombres de la misma manera. La biblioteca estándar proporciona E / S y (a partir de C ++ 11) subprocesos, y el soporte del sistema de archivos se está estandarizando.
Josh Kelley
@JoshKelley: Eso es básicamente nada comparado con lo que requieren la mayoría de los programas. Además, algunos compiladores muy comunes como MSVC implementan la sobrecarga, SFINAE y la búsqueda de nombres de manera diferente con diferentes resultados observables.
DeadMG
1

En términos muy simples, lo que hace que un programa sea multiplataforma es su capacidad de tomar las fuentes de un entorno, compilarlas en otro y hacer que el producto terminado funcione como se espera.

En términos menos simples, tiene una superposición total entre lo que el programa espera que esté disponible y lo que proporcionan sus entornos de destino. Una vez que hace algo que hace que la superposición sea inferior al 100%, como usar una biblioteca específica del entorno o una función de lenguaje con un comportamiento indefinido, ha vinculado su programa a los entornos que pueden proporcionar las funciones que no se superponen.

("Plataforma" es una palabra un poco blanda. La gente puede hablar de Windows y Unix como plataformas o Linux, OS X, BSD y Solaris como plataformas a pesar de que todos son nominalmente Unix. Revuelva ejecutando cualquiera de los anteriores en diferentes las arquitecturas de hardware y las cosas se vuelven aún más nebulosas. Habiendo dicho eso, comenzaré a usar la palabra).

Afortunadamente, hay estándares para aliviar este problema:

Idiomas Está escribiendo C ++, que fue estandarizado por primera vez por la ISO en 1998. Cualquier programa que escriba que cumpla con ese estándar puede compilarse y ejecutarse con los resultados esperados en cualquier plataforma con un compilador y tiempo de ejecución conformes. No hay límite para el tamaño o la sofisticación del programa siempre que no se desvíe del estándar. Si un programa que cumple con el estándar no se ejecuta como se esperaba en una plataforma determinada, la implementación del lenguaje en esa plataforma se vuelve sospechosa. Muchos idiomas tienen conjuntos de pruebas cuidadosamente diseñados que pueden usarse para verificar la conformidad.

Java recibe una mención especial porque no solo estandariza un lenguaje, sino que también estandariza el código objeto, lo que hace que sus programas sean ejecutables en cualquier lugar sin recompilación. Esto se logra empujando el punto de conformidad hacia abajo una capa adicional en una máquina virtual personalizada de plataforma (o incluso hardware) que es capaz de ejecutar el código objeto.

APIs. Las llamadas que realiza para que su programa haga ciertas cosas también se pueden estandarizar. Al igual que los lenguajes, estas API y las bibliotecas que las implementan se pueden configurar para que se comporten como los que llaman utilizan una implementación subyacente adecuada para una plataforma en particular. Una de esas API son los estándares POSIX de IEEE , que surgieron como una forma de detener la fragmentación que estaba ocurriendo en Unix durante la década de 1980. (Estaba por ahí; ese aspecto no era divertido). Al definir las llamadas y el comportamiento estándar, los proveedores de sistemas podían darles a sus clientes la confianza de que migrar a su sistema operativo no supondría una gran cantidad de trabajo como lo había hecho en el pasado. POSIX fue ampliamente adoptado y todavía se usa ampliamente casi 30 años después.

He realizado numerosos proyectos que se adhirieron servilmente a los estándares porque sabía que iban a tener que ejecutarse en múltiples plataformas. Lo que obtuve por mis problemas fue un código que funcionaba en todas partes donde había planeado ejecutarlo y me sorprendió gratamente en algunos donde no lo había hecho.

Blrfl
fuente
0

Básicamente, cuando 'tocas' cosas fuera de tu programa. Un caso particular (no me atrevo a decir el único caso) es cuando usa bibliotecas relacionadas con el sistema operativo. Cosas como usar memoria compartida entre el proceso e imprimir cosas sofisticadas en la consola. En el primer caso, accede a un fragmento de memoria que maneja el sistema operativo, en el segundo caso, la pantalla también es controlada por el sistema operativo.

Hacer una GUI depende del sistema operativo, pero hay bibliotecas de GUI hechas para ser multiplataforma, por lo que no tiene que preocuparse por eso. Al menos en teoría.

Es difícil hacer que algo no trivial sea multiplataforma. La buena noticia es que si usa las bibliotecas correctas y realiza las pruebas adecuadas, no es tan difícil hacer que el software sea portátil, al menos si el código no es demasiado grande. Cuán grande es demasiado grande depende del tamaño de su equipo, la experiencia en programación, etc.

cauchy
fuente