Hola SplinterGU,
necesito hacer lo siguiente
definir una variable en c en mi módulo, darle un valor, y luego compartirla con el exterior, para que desde el código .prg pueda acceder a ésta y cambiarle su valor.
¿Como se hace? he visto el código de mod_cd y otro y nada no capto la funcionalidad de DLVARFIXUP
parece que creas una estructura en bennu llamada cdinfo y luego compartes sus variables al exterior, pero si esto es así, como inicializo su valor y como se modifica desde mi programa prg que incluirá el módulo,
Gracias de antemano.
/* ----------------------------------------------------------------- */
/* Definicion de variables globales (usada en tiempo de compilacion) */
char * __bgdexport( mod_cd, globals_def ) =
"STRUCT cdinfo\n"
" current_track;\n"
" current_frame;\n"
" tracks;\n"
" minute;\n"
" second;\n"
" subframe;\n"
" minutes;\n"
" seconds;\n"
" subframes;\n"
" STRUCT track[99]\n"
" audio;\n"
" minutes;\n"
" seconds;\n"
" subframes;\n"
" END;\n"
"END;\n" ;
/* ----------------------------------------------------------------- */
/* Son las variables que se desea acceder. */
/* El interprete completa esta estructura, si la variable existe. */
/* (usada en tiempo de ejecucion) */
DLVARFIXUP __bgdexport( mod_cd, globals_fixup )[] =
{
/* Nombre de variable global, puntero al dato, tama±o del elemento, cantidad de elementos */
{ "cdinfo.current_track", NULL, -1, -1 },
{ "cdinfo.current_frame", NULL, -1, -1 },
{ "cdinfo.tracks", NULL, -1, -1 },
{ "cdinfo.minute", NULL, -1, -1 },
{ "cdinfo.second", NULL, -1, -1 },
{ "cdinfo.subframe", NULL, -1, -1 },
{ "cdinfo.minutes", NULL, -1, -1 },
{ "cdinfo.seconds", NULL, -1, -1 },
{ "cdinfo.subframes", NULL, -1, -1 },
{ "cdinfo.track", NULL, -1, -1 },
{ NULL, NULL, -1, -1 }
};
Splinter, esto mas o menos creo que ya lo he zanjado, a ver si estoy en lo cierto.
Lo anterior crea la variable en el ámbito de bennugd.
Para acceder a ella desde c, hay que usar GLODWORD o derivados.
Por ejemplo, para guardar un dato
GLODWORD( mod_notes, WHOLE_NOTE_TIME ) = 1;
para leer el dato
int temp = GLODWORD( mod_notes, WHOLE_NOTE_TIME );
Ahora tengo otras dudas que creo que son más avanzadas, tengo definidas unas constantes de tipo float, el compilador de c me da un warning de conversión a entero y luego cuando las uso en Bennu, efectivamente no son float aunque moddesc diga que sí lo son.
Como puedo solucinar este problemilla.
DLCONSTANT __bgdexport( mod_notes, constants_def )[] =
{
{"LONGA", (BASETYPE)TYPE_FLOAT, 4},
{"CUADRADA", (BASETYPE)TYPE_FLOAT, 2},
{"REDONDA", (BASETYPE)TYPE_FLOAT, 1},
{"BLANCA", (BASETYPE)TYPE_FLOAT, 1/2.0},
{"NEGRA", (BASETYPE)TYPE_FLOAT, 1/4.0},
{"CORCHEA", (BASETYPE)TYPE_FLOAT, 1/8.0 },
{"SEMICORCHEA", (BASETYPE)TYPE_FLOAT, 1/16.0},
{"FUSA", (BASETYPE)TYPE_FLOAT, 1/32.0},
{"SEMIFUSA", (BASETYPE)TYPE_FLOAT, 1/64.0},
{"GARRAPATEA", (BASETYPE)TYPE_FLOAT, 1/128.0},
{ NULL , (BASETYPE)0 , 0 }
};
Y otro más es que no sé porqué motivo no me funcionan las siguientes funciones de inicialización y de finalización
void __bgdexport( mod_notes, module_initialize )()
{
if ( !SDL_WasInit( SDL_INIT_AUDIO ) ) SDL_InitSubSystem( SDL_INIT_AUDIO );
GLODWORD( mod_notes, WHOLE_NOTE_TIME ) = DEF_WHOLE_NOTE_TIME;
desiredSpec.freq=22050; /* 22050Hz - FM Radio quality */
desiredSpec.format=AUDIO_S16LSB; /* 16-bit signed audio */
desiredSpec.channels=0; /* Mono */
desiredSpec.samples=8192;/* Large audio buffer reduces risk of dropouts but increases response time */
desiredSpec.callback = audio_callback;
desiredSpec.userdata = 0;
// you might want to look for errors here
SDL_OpenAudio(&desiredSpec, &obtainedSpec);
// start play audio
SDL_PauseAudio(0);
}
/* --------------------------------------------------------------------------- */
void __bgdexport( mod_notes, module_finalize )()
{
if ( SDL_WasInit( SDL_INIT_AUDIO ) ) SDL_QuitSubSystem( SDL_INIT_AUDIO );
}
Las defino así, pero luego en el código BennuGD cuando pongo el import "mod_notes" y uso alguna función de esta librería veo que no está inicializada, es decir no pasa por lo que tengo puesto en void __bgdexport( mod_notes, module_initialize )().
Para salir del paso, he creado una función notes_init() que hace justo eso y que el usuario debe de llamar obligatoriamente antes de poder usar el módulo.
¿Como solvento esto también? Gracias.
para floats te la vas a tener que apañar vos a mano... mira el dlvarcc.h, y como se acceden a los floats en el core para darte una idea...
declaras constantes que son para indicar el order dentro del fixup... y que luego usaras con los LOC* o GLO*... declaras las variables como lo harias en un prg en globals_def o en locals_def, segun necesidad...
y nada, bennu se encarga solo...
la inicializacion se hace, solo que hay macros para floats por el momento...
seguro no quedo claro, pero te sugiero que veas el codigo de mod_sound...
po mas dejao igual.
por otro lado
Quote
la inicializacion se hace, solo que hay macros para floats por el momento...
¿querias decir?
la inicializacion se hace, solo que
NO hay macros para floats por el momento...
exacto! eso quise decir... je, ves como puedes... pon el codigo y te digo que hace falta y que esta demas...
Bueno, a ver, he estado examinando lo que me dijiste SpliterGU, y me he dado cuenta que el array de constantes no se maneja de forma distinta al de locales y globales.
Lo que comentabas de que era un índice hacia el array de constantes no es así sino que es el valor asignado a la constante. Voy a ponerte pruebas.
Primeramente, he visto que el tipo de dato más complejo de constante que has declarado es un dword, y yendo más lejos solo has declarado constantes de tipo int y de tipo dword en todo el código bennu.
Quote from: librender.c
DLCONSTANT __bgdexport( librender, constants_def )[] =
{
{ "C_SCREEN", TYPE_DWORD, C_SCREEN },
{ "PARTIAL_DUMP", TYPE_DWORD, 0 },
{ "COMPLETE_DUMP", TYPE_DWORD, 1 },
{ "NO_RESTORE", TYPE_DWORD, -1 },
{ "PARTIAL_RESTORE", TYPE_DWORD, 0 },
{ "COMPLETE_RESTORE", TYPE_DWORD, 1 },
{ "BACKGROUND", TYPE_DWORD, 0 },
{ "SCREEN", TYPE_DWORD, -1 },
{ "SCALE_SCALE2X", TYPE_DWORD, SCALE_SCALE2X },
{ "SCALE_HQ2X", TYPE_DWORD, SCALE_HQ2X },
{ "SCALE_SCANLINE2X", TYPE_DWORD, SCALE_SCANLINE2X },
{ "SCALE_NORMAL2X", TYPE_DWORD, SCALE_NOFILTER },
{ "SCALE_NOFILTER", TYPE_DWORD, SCALE_NOFILTER },
{ NULL , 0 , 0 }
} ;
Quote from: mod_cd.c
DLCONSTANT __bgdexport( librender, constants_def )[] =
{
{ "C_SCREEN", TYPE_DWORD, C_SCREEN },
{ "PARTIAL_DUMP", TYPE_DWORD, 0 },
{ "COMPLETE_DUMP", TYPE_DWORD, 1 },
{ "NO_RESTORE", TYPE_DWORD, -1 },
{ "PARTIAL_RESTORE", TYPE_DWORD, 0 },
{ "COMPLETE_RESTORE", TYPE_DWORD, 1 },
{ "BACKGROUND", TYPE_DWORD, 0 },
{ "SCREEN", TYPE_DWORD, -1 },
{ "SCALE_SCALE2X", TYPE_DWORD, SCALE_SCALE2X },
{ "SCALE_HQ2X", TYPE_DWORD, SCALE_HQ2X },
{ "SCALE_SCANLINE2X", TYPE_DWORD, SCALE_SCANLINE2X },
{ "SCALE_NORMAL2X", TYPE_DWORD, SCALE_NOFILTER },
{ "SCALE_NOFILTER", TYPE_DWORD, SCALE_NOFILTER },
{ NULL , 0 , 0 }
} ;
Viendo por ejemplo lo resaltado en negrita, ya me contarás cómo van a haber dos constantes con el mismo índice en el array de constantes.
Por otro lado, si examinamos el código del núcleo nos encontramos lo siguiente:
Quote from: c_main.c
constants_def = ( DLCONSTANT * ) _dlibaddr( library, "constants_def" ) ;
if ( constants_def )
{
while ( constants_def->name )
{
int code = identifier_search_or_add( constants_def->name ) ;
constants_add( code, typedef_new( constants_def->type ), constants_def->code ) ;
constants_def++ ;
}
}
tambíen se ve lo mismo en:
Quote from: main_core.c
main_core.c
{
int i = 0, code ;
while ( constants_def.name )
{
code = identifier_search_or_add( constants_def.name ) ;
constants_add( code, typedef_new( constants_def.type ), constants_def.code ) ;
i++ ;
}
token_init( globals_def, -1 ) ;
compile_varspace( &global, globaldata, 1, 1, 0, NULL, DEFAULT_ALIGNMENT, 0 ) ;
token_init( locals_def, -1 ) ;
compile_varspace( &local, localdata, 1, 1, 0, NULL, DEFAULT_ALIGNMENT, 0 ) ;
}
hace un constants_add, que imagino yo que será para insertar en el array de constentes una constante con índice "code" (supongo que buscado en el array de constantes "identifier_search_or_add"), tipo "typedef_new( constants_def->type )" y valor "constants_def->code" que es justo el tercer campo del struct de una constante y es el que ponemos en tercer lugar en su asignación, como podemos ver en
Quote from: main_core.c
static struct
{
char * name ;
int type ;
int code ;
}
constants_def[] =
...
Ahora bien, esta es la que usa el nucleo para insertar en el array de constantes la constante en cuestión, pero luego al pasarlo al array de constantes veo que la estructura es otra
Quote from: constants.h
typedef struct _constant
{
int code ;
int value ;
TYPEDEF type ;
}
CONSTANT ;
extern void constants_init () ;
extern void constants_dump () ;
extern void constants_add (int code, TYPEDEF type, int value) ;
extern CONSTANT * constants_search (int code) ;
De esta estructura puedo deducir que actualmente bennu solo permite constantes de tipo "int" de C. (Bueno, haciendo piñuelas podremos meter cualquier cosa que no supere el tamaño de un int de C)
Así que tanto si pones type_dword como type_int a bennu le da igual y lo asigna a un int. También deduzco que si un int tiene capacidad para almacenar un dword como mínimo para compilar bennu debemos estar en máquinas de 32 bits :D. (byte = 8, word = 16, dword = 32).
Todo esto referente a constantes.
Ahora tengo una pregunta acerca de las globales, veo que siempres pones los últimos campos a NULL,-1,-1.
como por ejemplo en:
Quote from: libscroll.c
DLVARFIXUP __bgdexport( libscroll, globals_fixup )[] =
{
/* Nombre de variable global, puntero al dato, tamaño del elemento, cantidad de elementos */
{ "scroll" , NULL, -1, -1 },
{ NULL , NULL, -1, -1 }
};
Supongo que así es para decirle que calcule internamente los valores, pero ¿como se utilizarían manualmente?
puntero al dato: esto que sería a un dato creado dinámicamente en c?
tamaño del elemento: esto que seria el tamaño del dato en bytes?
cantidad de elementos: ya con esto me matas :) esto qué es, por si es un array lo que te inserto?
Venga, saludos, y gracias de antemano.
EDIT: Lo de las macros que comentas que no hay para floats ya he visto que es para globals y locals.
tooma geroma pastillas de goma, le inserté un valor en módulo 2 en hexadecimal al dato constante y se lo ha tragado com papas Bennu.
Juas, juas, he insertado un float en un int, que bueno soy. Gracias a que ambos datos ocupan los mismos bytes en memoria que si noo.
vamos por partes...
1) el index que mencionaba no es para las constantes, es para los FIXUPS y usarlos luego con los LOC* o GLO*... cuando dije "declaras constantes que son para el orden... blah..." me referia a constantes C (#define), no me referia a constantes Bennu... disculpas por no haber sido mas claro...
2) ahora que lo miro bien, las constantes solo pueden ser enteras.
Bueno, ya no es problema, ya se como meter floats como constantes. Pasas el valor del float a hexadecimal y lo insertas como 0x"valor".
Lo que me he encontrado es con un problema, creo que más gordo. Las funciones solo devuelven enteros.
function devolver_floats()
private
float retorno;
begin
retorno = 6.39;
return retorno;
end
begin
say(devolver_floats());
end
En la pantalla aparece 6
Lo he solvetado con la siguiente triquiñuela
local
float mi_float;
end
function devolver_floats(float * retorno)
begin
*retorno = 6.39;
return *retorno;
end
begin
devolver_floats(&mi_float);
say(mi_float);
end
esto pone en pantalla 6.39.
Bueno, esto no creo que sea un problema.
Es que es así...C es así.
Si quieres devolver otro tipo de valores, tienes que usar parámetros pasados por referencia (es decir, punteros).
C que va a ser así, en c puedes devolver de todo, hasta estructuras completas si quieres;
typedef struct st_mi_estructura_compleja{
int dato1;
char dato2;
float dato3;
double dato4;
int * puntero;
}tst_mi_estructura_compleja;
tst_mi_estructura_compleja unafuncion_que_devuelve_estructuras_complejas(int parametro_entrada_1)
{
tst_mi_estructura_compleja st_de_retorno;
st_de_retorno.dato1 =parametro_entrada_1;
st_de_retorno.dato2 = 'a';
st_de_retorno.dato3 = 3.0;
st_de_retorno.dato4 = 5.0;
st_de_retorno.puntero =0;
return st_de_retorno;
}
int main(int argc, char*argv[])
{
st_mi_estructura_compleja misdatos;
misdatos=unafuncion_que_devuelve_estructuras_complejas(100);
printf("dato1: %d\n",misdatos.dato1);
printf("dato2: %c\n",misdatos.dato2);
printf("dato3: %f\n",misdatos.dato3);
printf("dato4: %f\n",misdatos.dato4);
printf("puntero: %p\n",misdatos.puntero);
}
Creo que te has liado con lo que no puede devolver más de un dato, ni pasar parámetros por referencia, esto es lo que se simula con los punteros.
Pero ya en c++ suplieron lo de los parámetros por referencia.
Quote from: DCelso on February 25, 2010, 11:00:37 PM
Bueno, ya no es problema, ya se como meter floats como constantes. Pasas el valor del float a hexadecimal y lo insertas como 0x"valor".
Lo que me he encontrado es con un problema, creo que más gordo. Las funciones solo devuelven enteros.
function devolver_floats()
private
float retorno;
begin
retorno = 6.39;
return retorno;
end
begin
say(devolver_floats());
end
En la pantalla aparece 6
Lo he solvetado con la siguiente triquiñuela
local
float mi_float;
end
function devolver_floats(float * retorno)
begin
*retorno = 6.39;
return *retorno;
end
begin
devolver_floats(&mi_float);
say(mi_float);
end
esto pone en pantalla 6.39.
1) eso de ponerlo como hexa funciona, pero no es lo adecuado... cuando en algun tiempo lo quieras tocar o lo quiera seguir algun otro no va a saber que quisiste poner...
2) si declaras la funcion como float (y antes de su uso) funcionara... (ya fue dicho muchas veces esto...)
¿Como se declara una función como float?
Antes de preguntarlo busqué por el foro y wiki todo acerca de functions y no encontré nada.
Si nos lo cuentas, lo insertaré en la wiki.
Voy a buscar de nuevo a ver si ahora sabiendo a ciencia cierta que hay algo lo encuentro :D.
:P
function float devolver_floats()
begin
return 6.39;
end
admiti que fue una pregunta tonta...
DCelso, ¿De verdad no sabías declarar una función como float?
Me ofendes... He visto tus módulos y no me esperaba esa pregunta de tí... Se me ha caído un mito...
pues no, nunca lo necesité y no viene documentado :(, no pensé que fuese tan raro.
Es una mezcolanza entre cómo sería en c y pascal, vaya injerto raro, yo probé como debería de haber sido en pascal
function mifuncion( int mi_parametro) : float
begin
end
Y como debería de haber sido en c
float mifuncion(int mi_parametro)
begin
end
Y ninguna me fue, jamás se me pasó por la cabeza mezclarlas :D, tonto de mi:(.
Siento que me tengais tan supravalorado :D. Soy normal, no se de todo y erro como cualquier ser humano :(, otra vez.
En serio, ¿Todo el mundo lo sabía? vamos no me lo creo. :D
Tranquilo, DCelso, algunos no sabemos ni hacer un módulo mod_hola_mundo :D :D :D
Verás que risa cuando nos pongamos ;D
jejeje... no te hagas drama, yo pense que ya lo sabias, se hablo varias veces de como declarar y se dijo tambien muchas veces que si no declarabas la funcion antes de usarla o si no le ponias el tipo, el retorno por defecto era int...
en realidad no es ninguna mezcla ni nada raro, FUNCTION/PROCESS son los keywords... y luego viene el prototipo de la funcion... es bastante intuitivo...
yo creo que esta documentado...
pero nada, a cualquiera le pasa...
Nada, no tengo escusas, está documentado, y bien documentado encima, que malo soy leyendo, mira que lo miré como 15 veces en la wiki. :(, podeis brearme que me lo merezco :).
"brearte" y emplumarte como el monkey island?
;D
jaja