[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: interacting with gc
- From: pierre <pierre.saunier@...>
- Date: Tue, 7 Mar 2017 18:11:23 +0100
Hi,
How can I interact with the lua gc from the C API? What am I looking for
is not how to launch or block the gc of lua, but how can I tell lua,
from the API, that a resource is being used?
For example, while binding a GUI library, a button can have an image
attached. The image and the button are userdata type, both created in
lua (via the C API), but the image is linked to the button also via the
C API. so, lua has no way to know that the image cannot be freed because
linked to another object outside of its control.
How can I tell lua the resource is being used and then no more used
(block from gc or ready for gc)?
may be add an entry "c_linked" of type table to the metatable of the button; and in this table,
add an entry per field and linked it the userdata that is attached to it so that lua sees a link?
should work, no?
Lastly, I am attaching a generated C binding. All comments on the
generated code are welcome....
Thanks a lot,
Craouette
#include <stdlib.h>
#include <stdio.h>
#ifdef __cplusplus
extern "C" {
#endif
#include "raster.h"
#ifdef __cplusplus
}
#endif
#ifdef __cplusplus
extern "C" {
#endif
#include "raster2.h"
#ifdef __cplusplus
}
#endif
#ifdef __cplusplus
extern "C" {
#endif
#include "resource.h"
#ifdef __cplusplus
}
#endif
#include "lua_rst.h"
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
extern FILE *luaDebugFile;
#include "lua_resource.h"
/*****************************************************************************/
void luaA_resource_object_from_resourceDef(lua_State *L, resourceDef *resource, int scriptOwned)
{
luaA_resource_object *self;
self = (luaA_resource_object *) lua_newuserdata(L, sizeof(luaA_resource_object));
luaL_getmetatable(L, "resources.resource");
lua_setmetatable(L, -2);
self->L = L;
self->luaOwned = scriptOwned;
if(luaDebugFile != NULL)
{
fprintf(luaDebugFile,
"luaA_resource_object_from_resourceDef for object 0x%p return 0x%p, scriptOwned=%d\n",
resource, self, self->luaOwned);
fflush(luaDebugFile);
}
self->resource = resource;
}
static int luaA_resource_object_new(lua_State *L)
{
luaA_resource_object *self;
self = (luaA_resource_object *) lua_newuserdata(L, sizeof(luaA_resource_object));
luaL_getmetatable(L, "resources.resource");
lua_setmetatable(L, -2);
self->L = L;
self->luaOwned = TRUE;
if(luaDebugFile != NULL)
{
fprintf(luaDebugFile,
"luaA_resource_object_new return 0x%p, scriptOwned=%d\n",
self, self->luaOwned);
fflush(luaDebugFile);
}
self->resource = (resourceDef *) gMalloc(sizeof(resourceDef));
memset(self->resource, 0, sizeof(resourceDef));
return 1;
}
static int luaA_resource_object_gc(lua_State *L)
{
luaA_resource_object *self;
self = *(luaA_resource_object **)lua_touserdata(L, 1);
if(luaDebugFile != NULL)
{
fprintf(luaDebugFile,
"luaA_resource_object_gc called on 0x%p for object 0x%p, scriptOwned=%d\n",
self, self->resource, self->luaOwned);
fflush(luaDebugFile);
}
if(self->luaOwned == TRUE)
{
gFree(self->resource);
}
return 0;
}
int luaA_resource_object_type_check(lua_State *L, int narg)
{
luaA_resource_object *self;
self = luaL_checkudata(L, narg, "resources.resource");
if(self == NULL)
return FALSE;
return TRUE;
}
char *luaA_resource_object_str(resourceDef *resource)
{
char *str, *propStr, *tmpStr, *tmpObj;
int i, len;
char buffer[2048], *cStr;
str = gStrdup("{");
// key property
strcpy(buffer, " key: ");
cStr = buffer + strlen(buffer);
sprintf(cStr, "\"%s\"", resource->name==NULL?"null":resource->name);
strcat(buffer, ",\n");
gStrcat(&str, buffer);
// value property
strcpy(buffer, " value: ");
cStr = buffer + strlen(buffer);
sprintf(cStr, "\"%s\"", resource->str==NULL?"null":resource->str);
strcat(buffer, ",\n");
gStrcat(&str, buffer);
// raster property
strcpy(buffer, " raster: ");
cStr = buffer + strlen(buffer);
if(resource->rst == NULL)
{
strcpy(cStr, "null");
}
else
{
tmpStr = luaA_raster_object_str(resource->rst);
strcpy(cStr, tmpStr);
gFree(tmpStr);
}
strcat(buffer, ",\n");
gStrcat(&str, buffer);
gStrcat(&str, "}");
return str;
}
int luaA_resource_str(lua_State *L)
{
luaA_resource_object *self;
char *str;
self = luaL_checkudata(L, 1, "resources.resource");
luaL_argcheck(L, self != NULL, 1, "'resource' expected");
str = luaA_resource_object_str(self->resource);
lua_pushstring(L, str);
if(str != NULL) gFree(str);
return 1;
}
static int luaA_resource_get_key(lua_State *L)
{
luaA_resource_object *self;
resourceDef* resource;
char * value;
if(lua_gettop(L) != 1)
{
lua_pushstring(L, "key: getter requires 1 arguments");
lua_error(L);
return 0;
}
self = luaL_checkudata(L, 1, "resources.resource");
luaL_argcheck(L, self != NULL, 1, "'resource' expected");
resource = self->resource;
value = resource->name;
if(value == NULL)
{
lua_pushnil(L);
return 1;
}
lua_pushstring(L, value);
return 1;
}
static int luaA_resource_set_key(lua_State *L)
{
luaA_resource_object *self;
lua_pushstring(L, "key: read only property");
lua_error(L);
return 0;
}
static int luaA_resource_get_isRaster(lua_State *L)
{
luaA_resource_object *self;
resourceDef* resource;
unsigned char value;
if(lua_gettop(L) != 1)
{
lua_pushstring(L, "isRaster: getter requires 1 arguments");
lua_error(L);
return 0;
}
self = luaL_checkudata(L, 1, "resources.resource");
luaL_argcheck(L, self != NULL, 1, "'resource' expected");
resource = self->resource;
value = FALSE;
if(resource->resourceType == RASTER_RESOURCE_ID) value = TRUE;
lua_pushboolean(L, (int)value);
return 1;
}
static int luaA_resource_set_isRaster(lua_State *L)
{
luaA_resource_object *self;
lua_pushstring(L, "isRaster: read only property");
lua_error(L);
return 0;
}
static int luaA_resource_get_value(lua_State *L)
{
luaA_resource_object *self;
resourceDef* resource;
char * value;
if(lua_gettop(L) != 1)
{
lua_pushstring(L, "value: getter requires 1 arguments");
lua_error(L);
return 0;
}
self = luaL_checkudata(L, 1, "resources.resource");
luaL_argcheck(L, self != NULL, 1, "'resource' expected");
resource = self->resource;
value = resource->str;
if(value == NULL)
{
lua_pushnil(L);
return 1;
}
lua_pushstring(L, value);
return 1;
}
static int luaA_resource_set_value(lua_State *L)
{
luaA_resource_object *self;
resourceDef* resource;
char * value;
if(lua_gettop(L) != 2)
{
lua_pushstring(L, "value: setter requires 2 arguments");
lua_error(L);
return 0;
}
self = luaL_checkudata(L, 1, "resources.resource");
luaL_argcheck(L, self != NULL, 1, "'resource' expected");
resource = self->resource;
value = luaL_checkstring(L, 2);
if(resource->str != NULL) gFree(resource->str);
resource->str = gStrdup(value);
return 0;
}
static int luaA_resource_get_raster(lua_State *L)
{
luaA_resource_object *self;
resourceDef* resource;
rasterDef* value;
if(lua_gettop(L) != 1)
{
lua_pushstring(L, "raster: getter requires 1 arguments");
lua_error(L);
return 0;
}
self = luaL_checkudata(L, 1, "resources.resource");
luaL_argcheck(L, self != NULL, 1, "'resource' expected");
resource = self->resource;
value = resource->rst;
if(value == NULL)
{
lua_pushnil(L);
}
else
{
luaA_raster_object_from_rasterDef(L, value, FALSE);
}
return 1;
}
static int luaA_resource_set_raster(lua_State *L)
{
luaA_resource_object *self;
resourceDef* resource;
rasterDef* value;
if(lua_gettop(L) != 2)
{
lua_pushstring(L, "raster: setter requires 2 arguments");
lua_error(L);
return 0;
}
self = luaL_checkudata(L, 1, "resources.resource");
luaL_argcheck(L, self != NULL, 1, "'resource' expected");
resource = self->resource;
if(!luaA_raster_object_type_check(L, 2))
{
lua_pushstring(L, "resource: value argument should be a raster");
lua_error(L);
}
value = ((luaA_raster_object *)lua_touserdata(L, 2))->raster;
if(resource->resourceType != RASTER_RESOURCE_ID)
{
lua_pushstring(L, "Cannot set a raster to a string resource");
lua_error(L);
return 0;
}
return 0;
}
static int luaA_resource_object_index(lua_State *L)
{
luaA_resource_object *self;
char *str;
int res;
self = luaL_checkudata(L, 1, "resources.resource");
luaL_argcheck(L, self != NULL, 1, "'resource' expected");
str = luaL_checkstring(L, 2);
if(luaL_getmetafield(L, 1, str)) // no metafield?
{
return 1;
}
else
{
if(strcmp(str, "key") == 0)
{
lua_remove(L, 2);
res = luaA_resource_get_key(L);
return res;
}
if(strcmp(str, "isRaster") == 0)
{
lua_remove(L, 2);
res = luaA_resource_get_isRaster(L);
return res;
}
if(strcmp(str, "value") == 0)
{
lua_remove(L, 2);
res = luaA_resource_get_value(L);
return res;
}
if(strcmp(str, "raster") == 0)
{
lua_remove(L, 2);
res = luaA_resource_get_raster(L);
return res;
}
lua_pushfstring(L, "resource: Unknow property: %s", str);
lua_error(L);
}
return 1;
}
static int luaA_resource_object_newindex(lua_State *L)
{
luaA_resource_object *self;
char *str;
int res;
self = luaL_checkudata(L, 1, "resources.resource");
luaL_argcheck(L, self != NULL, 1, "'resource' expected");
str = luaL_checkstring(L, 2);
if(luaL_getmetafield(L, 1, str)) // no metafield?
{
return 1;
}
else
{
if(strcmp(str, "key") == 0)
{
lua_remove(L, 2);
res = luaA_resource_set_key(L);
return res;
}
if(strcmp(str, "isRaster") == 0)
{
lua_remove(L, 2);
res = luaA_resource_set_isRaster(L);
return res;
}
if(strcmp(str, "value") == 0)
{
lua_remove(L, 2);
res = luaA_resource_set_value(L);
return res;
}
if(strcmp(str, "raster") == 0)
{
lua_remove(L, 2);
res = luaA_resource_set_raster(L);
return res;
}
lua_pushfstring(L, "resource: Unknow property: %s", str);
lua_error(L);
}
return 1;
}
static const struct luaL_reg luaA_resource_f [] = {
{"get_key", luaA_resource_get_key},
{"set_key", luaA_resource_set_key},
{"get_isRaster", luaA_resource_get_isRaster},
{"set_isRaster", luaA_resource_set_isRaster},
{"get_value", luaA_resource_get_value},
{"set_value", luaA_resource_set_value},
{"get_raster", luaA_resource_get_raster},
{"set_raster", luaA_resource_set_raster},
{"__index", luaA_resource_object_index},
{"__newindex", luaA_resource_object_newindex},
{"__tostring", luaA_resource_str},
{"__gc", luaA_resource_object_gc},
{"new", luaA_resource_object_new},
{NULL, NULL} // sentinel
};
static int luaA_open_resource(lua_State *L)
{
luaL_newmetatable(L, "resources.resource");
lua_pushstring(L, "__index");
lua_pushvalue(L, -2); // pushes the metatable
lua_settable(L, -3); // metatable.__index = metatable
luaL_register(L, NULL, luaA_resource_f);
return 1;
}
/*****************************************************************************/
void luaA_resourceSet_object_from_resourceTableDef(lua_State *L, resourceTableDef *resources, int scriptOwned)
{
luaA_resourceSet_object *self;
self = (luaA_resourceSet_object *) lua_newuserdata(L, sizeof(luaA_resourceSet_object));
luaL_getmetatable(L, "resources.resourceSet");
lua_setmetatable(L, -2);
self->L = L;
self->luaOwned = scriptOwned;
if(luaDebugFile != NULL)
{
fprintf(luaDebugFile,
"luaA_resourceSet_object_from_resourceTableDef for object 0x%p return 0x%p, scriptOwned=%d\n",
resources, self, self->luaOwned);
fflush(luaDebugFile);
}
self->resourceSet = resources;
}
static int luaA_resourceSet_object_new(lua_State *L)
{
luaA_resourceSet_object *self;
self = (luaA_resourceSet_object *) lua_newuserdata(L, sizeof(luaA_resourceSet_object));
luaL_getmetatable(L, "resources.resourceSet");
lua_setmetatable(L, -2);
self->L = L;
self->luaOwned = TRUE;
if(luaDebugFile != NULL)
{
fprintf(luaDebugFile,
"luaA_resourceSet_object_new return 0x%p, scriptOwned=%d\n",
self, self->luaOwned);
fflush(luaDebugFile);
}
self->resourceSet = (resourceTableDef *) gMalloc(sizeof(resourceTableDef));
memset(self->resourceSet, 0, sizeof(resourceTableDef));
return 1;
}
static int luaA_resourceSet_object_gc(lua_State *L)
{
luaA_resourceSet_object *self;
self = *(luaA_resourceSet_object **)lua_touserdata(L, 1);
if(luaDebugFile != NULL)
{
fprintf(luaDebugFile,
"luaA_resourceSet_object_gc called on 0x%p for object 0x%p, scriptOwned=%d\n",
self, self->resourceSet, self->luaOwned);
fflush(luaDebugFile);
}
if(self->luaOwned == TRUE)
{
gFree(self->resourceSet);
}
return 0;
}
int luaA_resourceSet_object_type_check(lua_State *L, int narg)
{
luaA_resourceSet_object *self;
self = luaL_checkudata(L, narg, "resources.resourceSet");
if(self == NULL)
return FALSE;
return TRUE;
}
char *luaA_resourceSet_object_str(resourceTableDef *resources)
{
char *str, *propStr, *tmpStr, *tmpObj;
int i, len;
char buffer[2048], *cStr;
str = gStrdup("{");
gStrcat(&str, "}");
return str;
}
int luaA_resourceSet_str(lua_State *L)
{
luaA_resourceSet_object *self;
char *str;
self = luaL_checkudata(L, 1, "resources.resourceSet");
luaL_argcheck(L, self != NULL, 1, "'resourceSet' expected");
str = luaA_resourceSet_object_str(self->resourceSet);
lua_pushstring(L, str);
if(str != NULL) gFree(str);
return 1;
}
static int luaA_resourceSet_get(lua_State *L)
{
resourceTableDef *resources;
luaA_resourceSet_object *self;
char * key;
resourceDef *value;
if(lua_gettop(L) != 2)
{
lua_pushstring(L, "resourceSet.get requires 1 arguments");
lua_error(L);
return 0;
}
self = luaL_checkudata(L, 1, "resources.resourceSet");
luaL_argcheck(L, self != NULL, 1, "'resourceSet' expected");
resources = self->resourceSet;
key = luaL_checkstring(L, 2);
value = resourceTableGetElem(resources, key);
if(value == NULL)
{
lua_pushnil(L);
}
else
{
luaA_resource_object_from_resourceDef(L, value, FALSE);
}
return 1;
}
static int luaA_resourceSet_add(lua_State *L)
{
resourceTableDef *resources;
luaA_resourceSet_object *self;
resourceDef *resource;
if(lua_gettop(L) != 2)
{
lua_pushstring(L, "resourceSet.add requires 1 arguments");
lua_error(L);
return 0;
}
self = luaL_checkudata(L, 1, "resources.resourceSet");
luaL_argcheck(L, self != NULL, 1, "'resourceSet' expected");
resources = self->resourceSet;
if(!luaA_resource_object_type_check(L, 2))
{
lua_pushstring(L, "resourceSet.add: resource argument should be a resource");
lua_error(L);
}
resource = ((luaA_resource_object *)lua_touserdata(L, 2))->resource;
resourceTableAddElem(resources, resource);
return 0;
}
static int luaA_resourceSet_del(lua_State *L)
{
resourceTableDef *resources;
luaA_resourceSet_object *self;
resourceDef *resource;
if(lua_gettop(L) != 2)
{
lua_pushstring(L, "resourceSet.del requires 1 arguments");
lua_error(L);
return 0;
}
self = luaL_checkudata(L, 1, "resources.resourceSet");
luaL_argcheck(L, self != NULL, 1, "'resourceSet' expected");
resources = self->resourceSet;
if(!luaA_resource_object_type_check(L, 2))
{
lua_pushstring(L, "resourceSet.del: resource argument should be a resource");
lua_error(L);
}
resource = ((luaA_resource_object *)lua_touserdata(L, 2))->resource;
resourceTableDelElem(resources, resource);
return 0;
}
static int luaA_resourceSet_getString(lua_State *L)
{
resourceTableDef *resources;
luaA_resourceSet_object *self;
char * key;
char * defaultStr;
char * value;
if(lua_gettop(L) != 3)
{
lua_pushstring(L, "resourceSet.getString requires 2 arguments");
lua_error(L);
return 0;
}
self = luaL_checkudata(L, 1, "resources.resourceSet");
luaL_argcheck(L, self != NULL, 1, "'resourceSet' expected");
resources = self->resourceSet;
key = luaL_checkstring(L, 2);
defaultStr = luaL_checkstring(L, 3);
value = getRc(key, defaultStr, resources);
lua_pushstring(L, value);
return 1;
}
static int luaA_resourceSet_save(lua_State *L)
{
resourceTableDef *resources;
luaA_resourceSet_object *self;
char * fileName;
FILE *f; //@localvardef
if(lua_gettop(L) != 2)
{
lua_pushstring(L, "resourceSet.save requires 1 arguments");
lua_error(L);
return 0;
}
self = luaL_checkudata(L, 1, "resources.resourceSet");
luaL_argcheck(L, self != NULL, 1, "'resourceSet' expected");
resources = self->resourceSet;
fileName = luaL_checkstring(L, 2);
f = fopen(fileName, "wt");
if(f == NULL)
{
lua_pushstring(L, "Cannot open file");
lua_error(L);
return 0;
}
saveResourceTable(f, resources);
fclose(f);
return 0;
}
static const struct luaL_reg luaA_resourceSet_f [] = {
{"get", luaA_resourceSet_get},
{"add", luaA_resourceSet_add},
{"del", luaA_resourceSet_del},
{"getString", luaA_resourceSet_getString},
{"save", luaA_resourceSet_save},
{"__tostring", luaA_resourceSet_str},
{"__gc", luaA_resourceSet_object_gc},
{"new", luaA_resourceSet_object_new},
{NULL, NULL} // sentinel
};
static int luaA_open_resourceSet(lua_State *L)
{
luaL_newmetatable(L, "resources.resourceSet");
lua_pushstring(L, "__index");
lua_pushvalue(L, -2); // pushes the metatable
lua_settable(L, -3); // metatable.__index = metatable
luaL_register(L, NULL, luaA_resourceSet_f);
return 1;
}
/*****************************************************************************/
static int luaA_resources_newResources(lua_State *L)
{
resourceTableDef *value;
if(lua_gettop(L) != 0)
{
lua_pushstring(L, "resources.newResources requires 0 arguments");
lua_error(L);
return 0;
}
value = newResourceTable(128);
if(value == NULL)
{
lua_pushnil(L);
}
else
{
luaA_resourceSet_object_from_resourceTableDef(L, value, FALSE);
}
return 1;
}
static int luaA_resources_loadResources(lua_State *L)
{
char * fileName;
resourceTableDef *value;
if(lua_gettop(L) != 1)
{
lua_pushstring(L, "resources.loadResources requires 1 arguments");
lua_error(L);
return 0;
}
fileName = luaL_checkstring(L, 1);
value = loadResourceTable(fileName, 128, 0);
if(value == NULL)
{
lua_pushnil(L);
}
else
{
luaA_resourceSet_object_from_resourceTableDef(L, value, FALSE);
}
return 1;
}
static int luaA_resources_newStringResource(lua_State *L)
{
char * key;
char * val;
resourceDef *value;
if(lua_gettop(L) != 2)
{
lua_pushstring(L, "resources.newStringResource requires 2 arguments");
lua_error(L);
return 0;
}
key = luaL_checkstring(L, 1);
val = luaL_checkstring(L, 2);
value = newStringResource(key, val);
if(value == NULL)
{
lua_pushnil(L);
}
else
{
luaA_resource_object_from_resourceDef(L, value, FALSE);
}
return 1;
}
static int luaA_resources_newRasterResource(lua_State *L)
{
char * key;
rasterDef *val;
resourceDef *value;
if(lua_gettop(L) != 2)
{
lua_pushstring(L, "resources.newRasterResource requires 2 arguments");
lua_error(L);
return 0;
}
key = luaL_checkstring(L, 1);
if(!luaA_raster_object_type_check(L, 2))
{
lua_pushstring(L, "resources.newRasterResource: val argument should be a raster");
lua_error(L);
}
val = ((luaA_raster_object *)lua_touserdata(L, 2))->raster;
value = newRasterResource(key, val);
if(value == NULL)
{
lua_pushnil(L);
}
else
{
luaA_resource_object_from_resourceDef(L, value, FALSE);
}
return 1;
}
static const struct luaL_reg luaA_resources_f [] = {
{"newResources", luaA_resources_newResources},
{"loadResources", luaA_resources_loadResources},
{"newStringResource", luaA_resources_newStringResource},
{"newRasterResource", luaA_resources_newRasterResource},
{NULL, NULL} // sentinel
};
int luaA_open_resources(lua_State *L)
{
luaL_newmetatable(L, "resources");
lua_pushstring(L, "__index");
lua_pushvalue(L, -2); // pushes the metatable
lua_settable(L, -3); // metatable.__index = metatable
luaL_openlib(L, "resources", luaA_resources_f, 0);
lua_pushstring(L, "resource");
luaA_open_resource(L);
lua_settable(L, -3);
lua_pushstring(L, "resourceSet");
luaA_open_resourceSet(L);
lua_settable(L, -3);
return 1;
}
#ifndef __LUA_RESOURCE_H__
#define __LUA_RESOURCE_H__
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
extern FILE *luaDebugFile;
typedef struct {
lua_State *L;
int luaOwned;
resourceDef *resource;
} luaA_resource_object;
void luaA_resource_object_from_resourceDef(lua_State *L, resourceDef *resource, int scriptOwned);
int luaA_resource_object_type_check(lua_State *L, int narg);
char *luaA_resource_object_str(resourceDef *resource);
typedef struct {
lua_State *L;
int luaOwned;
resourceTableDef *resourceSet;
} luaA_resourceSet_object;
void luaA_resourceSet_object_from_resourceTableDef(lua_State *L, resourceTableDef *resources, int scriptOwned);
int luaA_resourceSet_object_type_check(lua_State *L, int narg);
char *luaA_resourceSet_object_str(resourceTableDef *resources);
int luaA_open_resources(lua_State *L);
#endif
#ifndef __LUA_RST_H__
#define __LUA_RST_H__
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
extern FILE *luaDebugFile;
typedef struct {
lua_State *L;
int luaOwned;
filter3x3Def *filter3x3;
} luaA_filter3x3_object;
void luaA_filter3x3_object_from_filter3x3Def(lua_State *L, filter3x3Def *filter, int scriptOwned);
int luaA_filter3x3_object_type_check(lua_State *L, int narg);
char *luaA_filter3x3_object_str(filter3x3Def *filter);
typedef struct {
lua_State *L;
int luaOwned;
filter5x5Def *filter5x5;
} luaA_filter5x5_object;
void luaA_filter5x5_object_from_filter5x5Def(lua_State *L, filter5x5Def *filter, int scriptOwned);
int luaA_filter5x5_object_type_check(lua_State *L, int narg);
char *luaA_filter5x5_object_str(filter5x5Def *filter);
typedef struct {
lua_State *L;
int luaOwned;
rasterDef *raster;
} luaA_raster_object;
void luaA_raster_object_from_rasterDef(lua_State *L, rasterDef *rst, int scriptOwned);
int luaA_raster_object_type_check(lua_State *L, int narg);
char *luaA_raster_object_str(rasterDef *rst);
int luaA_open_image(lua_State *L);
#endif