Esta es una versión completamente reescrita de an earlier question; Creo que la primera versión omitió detalles importantes; este proporciona todo el contexto.C/C++ puzzle API
Tengo un encabezado de alguna API de C++. La API declara algunas clases de esta manera:
class Foo
{
public:
inline void Bar(void);
/* more inlines */
private:
inline Foo();
/* maybe more inline constructors */
}
es decir, no miembros, todas las funciones son en línea y públicas, excepto constructores. Los constructores son privados, por lo que entiendo C++, realmente no puedo llamarlos. Para crear estos objetos se supone que debo utilizar auto_ptr
s a ellos:
class FooAutoPtr : public std::auto_ptr<Foo>
{
public:
inline FooAutoPtr();
/* one for each Foo constructors */
}
La API también tiene un segundo conjunto de funciones de la siguiente manera:
void Foo_Bar(void *self);
Foo* Foo_Constructor();
Llamémosles funciones básicas, porque estos son los símbolos realmente exportados desde la aplicación de host. No las clases de C++.
Las funciones principales tienen una vinculación C (es decir, declararon como extern "C"
), pero se declaran como tomar y devolver tipos C++ (por ejemplo, pueden tomar una referencia: Foo &foo
). Finalmente, el encabezado contiene la implementación de las funciones en línea de las clases de C++. Todas estas funciones hacen lo mismo: llaman a las funciones básicas. Por ejemplo, el FooAutoPtr
constructor es así:
inline FooAutoPtr::FooAutoPtr()
{
reset(Foo_Constructor());
}
Por lo que entiendo, el código recibe algún objeto que se supone que es un puntero a Foo
desde la aplicación host y cambia el aparatito auto_ptr
señalar a este objeto . Pero para el desarrollador, parece que fue un verdadero puntero al Foo
. Y llamando Foo::Bar()
es la siguiente:
inline Foo::Bar()
{
Foo_Bar(this);
}
Esto vale para todas las clases y los métodos de C++. Inteligente, ¿eh?
Ahora, ¿alguien podría explicar qué significa todo esto? :) No es una verdadera API de C++, ¿o sí? Para mí, parece más un envoltorio delgado de C++ sobre una API de C. Si es así, ¿puedo redeclarar las funciones básicas para perder los bits de C++? Entiendo cómo escribir un contenedor C en C++ (en realidad, ya lo escribí), pero, si es posible, prefiero perder el contenedor y usar las funciones directamente. ¿Pero cómo pierdo las cosas de C++?
Por ejemplo, podría haber una función con las referencias:
Bar& Foo_GetBar(void* self, const Baz& baz, int& i);
Ahora mismo llamarlo desde mi C++ envoltura de la siguiente manera:
typedef struct bar bar_t; /* and others */
/*...*/
bar_t*
foo_get_bar(foo_t* foo, baz_t* baz, int* i)
{
return (bar_t*) &Foo_GetBar(foo, *(Baz*)baz, *i);
}
y funciona (no tengo ni idea, cómo). Pero prefiero que se vuelve a declarar como esto:
/* type? */ Foo_GetBar(foo_t*, /* type? /*, /* type? */);
ACTUALIZACIÓN: He encontrado una cosa interesante que confirma Neil's answer. Es código en Common Lisp que usa la misma API. (Naturalmente, tiene que usar la parte C). Y, por lo que puedo (apenas) leer en la fuente, el autor simplemente usó punteros en lugar de referencias.He aquí un fragmento de código que convierte el C++ declaraciones a Lisp:
;; use * instead of & - we're not interested in C++ details
line (regex-replace-all "&" line "*")
Así que eso es todo :) Gracias a todos!
Wow, una pregunta que _legitimately_ etiquetó tanto 'c' como' C++ '. Una apariencia rara ... – ildjarn
Si las funciones básicas devuelven tipos C++ (referencias), entonces es una API C++ real (_not_ una API C), pero simplemente no es orientada a objetos. –
@SethCarnegie Así que eso es :) Ya ves, el encabezado incluso tiene un comentario cerca de las funciones básicas que dicen que son "para el entorno C-only". Bueno, otro comentario obsoleto :) –