2010-07-06 20 views
5

Tengo un proyecto de MS C++ (llamémosle proyecto A) que actualmente estoy compilando como una biblioteca estática (.lib). Define una variable global foo. Tengo otros dos proyectos que se compilan por separado (llámalos B y C, respectivamente) y cada uno vincula la biblioteca estática compartida A in. Tanto B como C son dll que terminan cargados en el mismo proceso. Me gustaría compartir una única instancia de foo de A entre B y C en el mismo proceso: un singleton. No estoy seguro de cómo lograr el patrón singleton aquí con el proyecto A, ya que está compilado estáticamente en B y C por separado. Si declaro foo como extern tanto en B como en C, termino con instancias diferentes en B y C. El uso de un patrón simple de clase singleton estándar con un método getInstance estático da como resultado dos instancias foo estáticas.Variable global compartida en la biblioteca estática de C++

¿Hay alguna manera de lograr esto mientras el proyecto A está compilado estáticamente en B y C? ¿O tengo que hacer que A sea una DLL?

+0

* "Si declaro foo como externo tanto en B como en C, termino con instancias diferentes en B y C." * - ¿Es esto realmente cierto? –

+0

Parece ser cierto: es el comportamiento que observo cuando paso por el programa mientras estoy depurando. Veo el constructor para foo llamado dos veces y las direcciones de las variables externas g_Foo son diferentes en los dos módulos B y C. ¿No debería ser así? – Zach

+0

posible duplicado de [¿Cómo implementar la variable global de proceso en C++?] (Http://stackoverflow.com/questions/669989/how-to-implement-process-global-variable-in-c) – Zach

Respuesta

4

Sí, debe definir A como una DLL compartida, o bien definirla como extern en B y C y vincular las tres estáticamente.

+0

¿Puede explicar lo que quiere decir con "vincular los tres estáticamente"? Actualmente estoy vinculando A estáticamente en B y C y declarando foo extern en B y C, sin embargo, termino con múltiples definiciones de foo en tiempo de ejecución. Creo que estás diciendo que necesitaría unir estáticamente A y B en C (o A y C estáticamente en B), o vincular A, B y C estáticamente en otra biblioteca. Es eso exacto? ¡Gracias! – Zach

+0

El último, excepto que sustituye "otra biblioteca" por "el ejecutable final". No vincules ninguna de las bibliotecas. En su lugar, vincula A, B y C estáticamente con tu ejecutable final. Cualquier símbolo de A que se use en B o C se debe declarar como externo en B y C, pero no se define. Si vincula A, B y C a otra biblioteca compartida, solo tiene que asegurarse de que esta biblioteca encapsula el singleton de A, ya que si A está vinculado estáticamente al ejecutable y el ejecutable accede directamente a los datos estáticos de A, obtendrá una copia diferente a la lib. –

2

No, no se comparten.

De Richter 'de Windows a través de C/C++' (P583):

Cuando uno proceso asigna un archivo de imagen DLL en su espacio de espacio de direcciones, el sistema crea instancias del mundial y datos estáticos variable también.

Por lo tanto, si necesita compartir un recurso entre varios ejecutables, deberá crear un objeto kernel compartido de algún tipo. Yo sugeriría crear una correlación de archivo con nombre, que luego se puede utilizar para leer y escribir a partir de los procesos separados

+0

Su observación es correcta en general, pero usted supervisó un reclamo importante realizado por el OP: "* Tanto B como C son archivos DLL que terminan cargados ** en el mismo proceso **. *" Así que con DLL sería compartido. El problema aquí es la vinculación estática. – Christophe

+0

Por cierto, el intercambio entre procesos se puede lograr fácilmente como se explica aquí: http://stackoverflow.com/a/7705793/3723423 – Christophe

0

puedo conseguir este problema podía comprender (con exclusión objeto mutex apropiado, por supuesto.):

Tengo una .EXE vinculado con B.LIB. Tengo C.DLL también vinculado con B.LIB.

Como se puede ver, estos dos programas están relacionados con B.LIB

Ahora, cuando sea necesario, la carga a.exe ir C.dll. Después de la carga, A.EXE y C.DLL tienen separados B.LIB para el código y los datos

El problema es que es posible tener un B.LIB "fantom" vinculado con C.DLL para usar el ya cargado en A.exe?

Creo que no. Es una limitación de Window. En Linux puedes, si no recuerdo mal. Eso fue lo que consideró la opción -fPic de GCC. Pero no estoy seguro.

La solución para compartir datos globales/estáticos almacenados en B.LIB con A.EXE y C.DLL es utilizar clases/interfaces compartidas. Su A.EXE envía la interfaz a C.DLL con un puntero de datos/interfaz al B.LIB almacenado en A.EXE.

En otras palabras, si su C.DLL necesita establecer/estado compartido de una variable estática en B.LIB, su A.EXE debe inicializar C.DLL con la interfaz para permitir el intercambio de datos con B.LIB en A.EXE.

En todo caso, el B.LIB almacenada en C.dll siguen a la hinchazón del programa mundial debido al código duplicado de B.LIB en A.EXE y C.dll

Para reducir la hinchazón global, debes dividir tu A.LIB en más D.DLL, E.DLL cargado por A.EXE y transmitido a través de la interfaz a su C.DLL

Para reducir el código inflado a cero, debe usar el método de interfaz independiente completo.

Cuestiones relacionadas