Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   C++ Builder (https://www.clubdelphi.com/foros/forumdisplay.php?f=13)
-   -   cabecera perdida para dll (https://www.clubdelphi.com/foros/showthread.php?t=54216)

Guillermo80 11-03-2008 22:21:27

cabecera perdida para dll
 
Hola foreros, comento mi problema. Estoy preparando una dll a partir de un código que a tiene todos los .hy .c. Para ello me estoy creando todos los headers equivalentes en una unidad de Delphi, que será el lenguaje en el que voy a usar la dll, y sólo me queda uno por hacer, he aquí el problema. Llegado este punto, previo al gran problemón:

Cita:

struct FLAC__StreamEncoderProtected;
struct FLAC__StreamEncoderPrivate;

typedef struct {
struct FLAC__StreamEncoderProtected *protected_;
struct FLAC__StreamEncoderPrivate *private_;
} FLAC__StreamEncoder;
Total, que me lo defino en mi .pas de delphi, y ahora, cuando necesito los headers, encuentro el de FLAC__StreamEncoderProtected, pero el FLAC__StreamEncoderPrivate no está en un .h sino en un .c, lo cual me dejó un poco mosca.

Ahora resulta que es un registro enorme con montones y montones de campos, y que hace alusiones a no pocos tipos predefinidos en otros .h que no he incluido aún, y me resulta de lo más sospechoso todo esto, llevo la mitad traducido y me queda bastante aún, y no sé si lo estoy haciendo bien, por el hecho de no venir definido en un .h.

¿Qué sugerencia podríais darme?¿Hay que sacrificarse de lleno o hay alguna alternativa?

He estado mirando si realmente voy a usar todos los campos del registro, para definir sólo aquellos que necesite, pero resulta que en la función más importante hace:

Cita:

FLAC__StreamEncoder enconder;
encoder->private_ = (FLAC__StreamEncoderPrivate*)calloc(1, sizeof(FLAC__StreamEncoderPrivate));
Por lo que reserva memoria para el registro private, que debe ser del tamaño que viene en el .c, así que me estropea el invento de "ahorrar campos".

Estoy desesperado, por favor, una ayuda quiero¡¡¡

escafandra 12-03-2008 00:04:28

No termino de entender del todo el problema, pero si defines FLAC__StreamEncoderPrivate como una estructura con menos campos...
Código:

calloc(1, sizeof(FLAC__StreamEncoderPrivate));
reservará espacio para esa estructura de menos campos...

De todas formas, una definición en C puede estar en una cabecera.h o en un .c. La diferencia está que si la defines en el .c o .cpp, solo sera reconocida en ese archivo y no será exportable a otros módulos, al menos en principio (hay trucos...). Esto quiere decir que esa definición que hechas en falta en una libreria.h tu la puedes predefinir, al traducirla, donde te venga bien, al fin y al cabo, las librerías.h no son otra cosa que archivos de declaración o predefinición.

Por otro lado no entiendo el empeño de traducir toda la dll, si al final estará compilada en una dll. ¿No es mas fácil y práctico hacer las llamadas oportunas desde delphi aunque la libreria original este en c++?. En fin, supongo que tus motivos tendrás.

Saludos.

Guillermo80 12-03-2008 08:30:58

No del todo
 
Bueno, realmente no estoy traduciendo toda la dll, sino solo aquellas cabeceras que vaya a utilizar en mi programa de Delphi las traduzco en una unidad .pas. Lo que pasa es que si traduzco una función que lleva una parámetro de entrada que sea FLAC__StreamEncoder, entonces me veo obligado a declarar ese registro, que a su vez tiene dos campos que son los registros FLAC__StreamEncoderProtected y FLAC__StreamEncoderPrivate, que a su vez me obliga a declarar sus contenidos. El tema de traducir todo esto es que esté más "accesible" a la hora de hacer las llamadas desde mi programa principal en Delphi que use esa dll (libFlac.dll).

Tengo una teoría: ¿podría ser que la declaración adelantada:

Cita:

struct FLAC__StreamEncoderProtected;
struct FLAC__StreamEncoderPrivate;
...me evite el tener que declarar en mi unidad .pas esos contenidos, y que se definan al hacer en una función de inicialización la instrucción (en un .c):

Cita:

FLAC__StreamEncoder encoder; //contiene los registros arriba mencionados sin definir
encoder->private_ = (FLAC__StreamEncoderPrivate*)calloc(1, sizeof(FLAC__StreamEncoderPrivate));
...teniendo en cuenta que esta llamada se hace desde el .c en el que está definida correctamente FLAC__StreamEncoderPrivate? calloc reserva el espacio necesario para el FLAC__StreamEncoderPrivate definido en ese mismo .c, y lo asignaría a encoder->private que es el que está sin definir y que tras esa asignación hecha por calloc quedaría declarado y definido correctamente ?

No sé si es una chaladura esto que propongo, pero tiene bastante sentido, además, creo que fuiste tú, Escafandra, quien me habló del uso de la "declaración adelantada" en declaraciones de struct del tipo

Cita:

struct FLAC__StreamEncoderPrivate;

escafandra 12-03-2008 11:38:23

Pues si lo unico que quieres traducir son las declaraciones externas de esa dll no te hace ninguna falta traducir nada mas que eso, es decir: sólo las funciones que tengas que usar en delphi, y que por lo tanto, el compilador debe conocer.

Si
Código:

struct FLAC__StreamEncoderProtected;
struct FLAC__StreamEncoderPrivate;

no las vas a llamar desde tu programa, y sólo son de uso interno.... No las traduzcas.

El hecho de que una declaración se realize en un *.c implica que no se va a usar desde otro archivo, de lo contrario el programador las declara en un *.h. En cpp puedes "incluir" (#include archivo.cpp) todo un archivo.c ó .cpp... Esto declararía todo lo declarado en ese archivo, pero no es ni habitual ni ortodoxo. De forma que es posible que no te haga falta declarar esas declaraciones hechas en tu archivo.c que comentabas en tu penúltimo post.

La forma se saberlo es compilar y llamar a tus funciones desde delphi. Si no tienes errores de compilación...

Saludos.

Guillermo80 12-03-2008 15:23:50

casi casi
 
Esos 2 registros no los uso directamente, pero el registro contenedor de ambos es un parámetro de entrada de una/s función que utilizo. Por tanto debería declarar ese registro contenedor. Si declaro el registro contenedor deberé declarar los registros que contengan, de ahí mi pregunta.

Pero si hago lo que tú me dices, y no declaro el registro contenedor, entonces el compilador no sabe de qué tipo es ese registro contenedor que le paso como parámetro a funciones de las que tengo declarada la cabecera en esa misma unidad.

Por favor, corrígeme si me equivoco. :o

Un saludo.

escafandra 12-03-2008 17:49:29

Si el registro contenedor es un parámetro de una función que utilizas, entonces tu programa debe conocerlo, ya que le pasas el parámetro que previamente le has preparado.

Pero puede ser que ese parámetro lo obtengas de otra función de la dll y que realmente no interese saber como está definido... Piensa que
Código:

typedef struct {
    struct FLAC__StreamEncoderProtected *protected_;
    struct FLAC__StreamEncoderPrivate *private_;
} FLAC__StreamEncoder;

no es mas que una estructura de dos punteros, que bien podría ser
Código:

typedef struct {
    void *protected_;
    void *private_;
} FLAC__StreamEncoder;

Si a ti te da igual, al compilador también.

Otra posibilidad es extraer la declaración de ese.c que comentas y colocarla en una cabecera.

Saludos.

Guillermo80 12-03-2008 20:23:19

me gusta
 
Me ha gustado la idea que propones, voy a aplicarla y voy a hacer algunas pruebas con una función de inicialización que usa la dichosa estructura a ver si funciona bien.;)

La 2ª idea que me propones es la versión "tediosa" que empecé haciendo, y que se iba convirtiendo en una "caja de pandora"; a cada campo que iba traduciendo le correspondía un tipo predefinido en otro header, que a su vez podía tener otro registro que...bla bla bla...y no acababa nunca.:(

Ya te comentaré si da resultado, muchas gracias por la ayuda¡¡


La franja horaria es GMT +2. Ahora son las 14:10:25.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi