2008-12-18 20 views
29

¿Es posible tener una API de biblioteca estática C, que utiliza C++ internamente y lo oculta a los usuarios de la biblioteca?Uso de librerías estáticas C/C++ desde iPhone Aplicaciones ObjectiveC

He escrito una biblioteca portátil de C++ Deseo vincular estáticamente a una aplicación de iPhone.

He creado un proyecto de Xcode utilizando la plantilla de "biblioteca estática" de Max OS X, y he copiado la fuente, además de escribir un C wapper (para tratar excepciones) usando (extern "C").

Estoy tratando de usar la biblioteca generada (archivo .a) en otra aplicación de Cocoa iPhone.

Todo funciona bien si utilizo las extensiones (.mm) en el archivo ObjectiveC llamante y (.cpp) en la clase de implementación en la biblioteca.

Pero obtengo símbolos no resueltos al vincular cuando trato de cambiar el archivo del contenedor a una extensión (.c), aunque todos los archivos de la función del contenedor son solo funciones C.

Simplemente porque C++ se usa internamente en una biblioteca, ¿significa que externamente debe tratarse como un programa C++? ¿No hay de todos modos para hacer cumplir esta abstracción?

Editar: Gracias por las respuestas,

que había estado utilizando extern "C", sólo estaba seguro sobre qué configuraciones cuando se requieran en el proyecto llamado. es decir. si el llamado proyectado requeriría saber si usó C++ o podría ser ignorante y pensar que es una biblioteca puramente de C.

Parece que no puedo, y debo usar archivos (.mm) en mis clases de ObjectiveC.

+0

¿Está declarando sus funciones de biblioteca C con extern "C"? –

+0

Akusete, su pregunta realmente no es acerca de Objective-C ... se trata de C/C++ y problemas de herramientas. Creo que su problema es que no está vinculando el soporte de tiempo de ejecución de C++ porque las cosas de Xcode están vinculando una aplicación C. No etiquetes con Obj-C si no hay nada específicamente sobre Obj-C en el Q –

+0

Mi error, no me di cuenta de que lo habías quitado. – Akusete

Respuesta

34

es muy difícil hacer esto en los comentarios, así que sólo voy a demostrar de forma rápida cuáles son los problemas de enlace son que usted está teniendo. Cuando Xcode encuentra archivos, usa reglas de compilación basadas en el sufijo para decidir qué compilador usar. Por defecto, gcc vincula los archivos a la biblioteca C estándar, pero no enlaza con la biblioteca C++ estándar. Los archivos de almacenamiento (bibliotecas estáticas) no tienen ninguna resolución de enlace realizada. Básicamente son un archivo de archivos de objetos que deben estar vinculados. Como no tiene archivos .mm o .cpp en su proyecto, nunca se llama a g ++ y sus archivos nunca se vinculan a las bibliotecas estándar. Para corregir esto, simplemente agregue las bibliotecas estándares de C++ a sus otros indicadores de enlazador en su proyecto de Xcode, o simplemente agréguelos a la opción de otros indicadores predefinidos como -l (por ejemplo, -lstdC++).

Aquí es una demostración rápida:

stw.h:

#ifdef __cplusplus 
extern "C" 
#endif 
void show_the_world(void); 

stw.cpp:

#include <iostream> 
#include "stw.h" 
using namespace std; 

extern "C" void show_the_world() { 
    cout << "Hello, world!\n"; 
} 

crear la biblioteca:

$ g++ -c stw.cpp -o stw.cpp -O0 -g 
$ ar rcs stw.a stw.o 

El uso de la biblioteca desde una aplicación C:

myapp.c:

#include "stw.h" 

int main() { 
    show_the_world(); 
    return 0; 
} 

La construcción de la aplicación C:

$ gcc -o myapp myapp.c stw.a -lstdc++ -g -O0 
$ ./myapp 
Hello, world! 
$ 

Si intenta compilar sin la -lstdC++ obtendrá todas las cuestiones sin resolver debido a que el compilador de C no tiene absolutamente ningún idea de que debería vincularse con el tiempo de ejecución de C++ (y por qué lo haría, ¿no es cierto??!?) por lo que debe agregarlo manualmente. La otra opción que tiene es cambiar la regla de compilación para su proyecto ... en lugar de usar Xcode gcc para compilar archivos .c y .m, dígale que use g ++ y sus problemas se resolverán.

+0

Gracias por su ayuda, mis disculpas por ser irritante. Soy un tanto ignorante de cómo funciona el tiempo de ejecución de C++, y anteriormente siempre había estado usando g ++ o VC++. – Akusete

+0

ah, no eres irritante en absoluto :) simplemente haciendo todo en 300 comentarios de carácter fue ... –

+0

Esto salvó mi tocino al traer las bibliotecas FMOD a mi proyecto directo de Objective-C. Debe incluir el -lstdC++ para deshacerse de los errores de enlace. – Batgar

2

Debe declarar las funciones que desea que sean visibles extern "C". Sus firmas necesitan ser compatibles con C, pero los contenidos no (puede acceder a objetos de C++, por ejemplo, pero no puede pasarlos directamente, los punteros están bien). Los símbolos serán visibles para cualquier entorno compatible con C.

EDITAR: Y compilarlo como un archivo de origen C++, C no tiene la noción de vinculación de lenguaje. Hay un par de otros problemas con el enlace del lenguaje (como el hecho de que todas las funciones extern "C" con el mismo nombre tienen la misma función, independientemente del espacio de nombres).

Edit2: En el encabezado, se puede comprobar para la macro __cplusplus, y el uso que establecer para C++ y otros lenguajes, respectivamente (porque C++ requerirá extern "C" declaraciones y otros idiomas, probablemente se quejará de ellos).

+0

Gracias, 'compilarlo como un archivo fuente C++' significa que todavía necesitaré un archivo Objective C (.mm) para usarlo ¿verdad? 'C no tiene la noción de vinculación de lenguaje' Supongo que eso significa que si tengo C++ en cualquier lugar dentro de una biblioteca, todo debe compilarse como C++. – Akusete

1

Básicamente, al compilar las funciones C con un compilador C++, modifica los nombres de las funciones y utiliza C++ ABI.

Cuando utiliza la extensión * .cpp o * .mm está utilizando el compilador de C++.

Lo que quiere hacer es forzar al compilador a generar funciones de C con nombres de anulación y utilizando el C ABI.

Usted puede hacer esto ya sea:

  • compilar con el compilador C.
  • compilar con el compilador de C++, pero asegúrese de que el prefijo de las declaraciones de funciones con extern "C"

Una forma preferida para configurar el archivo de cabecera, de modo que el mismo archivo se puede incluir tanto de C y C++ archivos de origen es:

#ifndef HEADER_GUARD_1_H 
#define HEADER_GUARD_1_H 

#ifdef __cplusplus 
extern "C" { 
#endif 

// Declare C function interface here. 
int myFunc(int x,char*); 

#ifdef __cplusplus 
} 
#endif 

#endif 
+0

Gracias, entiendo el uso de extern "C", la biblioteca actualmente funciona para C/C++/C# (usando pinvoke), en las plataformas win32 windowsCE y linux. No estoy seguro, sin embargo, si necesitaba usar (.mm) en el código objetivoC si mi interfaz era C. – Akusete

+1

.mm. Simplemente lo obliga a usar el compilador C++ en lugar del compilador C. Objective C es solo un contenedor en la parte superior de estos idiomas (no me refiero literalmente). –

+0

gracias por los consejos! –

1

gracias, por tan buena discusión.

lo que hice es:

1) He creado un lib estática utilizando la opción lib estática cocaotouch. En eso tengo c/C++/obj-c todo mezclado. sin embargo, mis exportaciones son solo clases obj-c. De hecho, utilicé objc- to c to C++.

2) luego creé la aplicación para el iphone en el proyecto X-code. he añadido las banderas otherlink mi nombre lib (-lxyz) // lib mi nombre es libxyz.a he añadido lib ruta de búsqueda, cabecera de Ruta de búsqueda de

3) a continuación he recopilado. Tengo errores diciendo oeprator new, delete del operador no encontrado.

3) luego aparte mi appdelegate, controlador de vista, agregué dummy cpp (.h, .cpp) ... atestdummy.h atestdummy.cpp

4) a continuación, voy a construir de nuevo ...

eso trabajaba.

Entonces, cualquier sugerencia que dieron antes me funcionó. motivo básico, a menos que su aplicación vea un archivo .cpp. El archivo .mm con código cpp, vinculado no usará g ++.

Gracias a todos. He leído lo anterior y resuelto mi problema.

u chicos son buenos para compartir.

Cuestiones relacionadas