改写 alien core使其可以适配lua5.3

/* Lua FFI using libffi */

/* Author: Fabio Mascarenhas */

/* License: MIT/X11 */

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <errno.h>

#include "lua.h"

#include "lualib.h"

#include "lauxlib.h"

#include "ffi.h"

#ifdef WINDOWS

#include <windows.h>

#define ALLOCA _alloca

#else

#include <sys/mman.h>

#include <unistd.h>

# if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)

#  define MAP_ANONYMOUS MAP_ANON

# endif

#define ALLOCA alloca

#endif

#define BLOCKSIZE _pagesize

#define ALIEN_LIBRARY_META "alien_library"

#define ALIEN_FUNCTION_META "alien_function"

#define ALIEN_BUFFER_META "alien_buffer"

#define ALIEN_CALLBACK_META "alien_callback"

#ifndef uchar

#define uchar unsigned char

#endif

typedef enum {

AT_SHORT,

AT_INT,

AT_LONG,

AT_VOID,

AT_FLOAT,

AT_DOUBLE,

AT_CHAR,

AT_BYTE,

AT_STRING,

AT_PTR,

AT_REFINT,

AT_REFCHAR,

AT_REFDOUBLE,

AT_CALLBACK

} alien_Type;

typedef struct _alien_Library {

void *lib;

char *name;

} alien_Library;

typedef struct _alien_Function {

alien_Library *lib;

void *fn;

char *name;

alien_Type ret_type;

ffi_cif cif;

ffi_type *ffi_ret_type;

int nparams;

alien_Type *params;

ffi_type **ffi_params;

} alien_Function;

typedef struct _alien_Callback {

/* alien_Function part! */

alien_Library *lib;

void *fn;

char *name;

alien_Type ret_type;

ffi_cif cif;

ffi_type *ffi_ret_type;

int nparams;

alien_Type *params;

ffi_type **ffi_params;

/* callback part */

lua_State *L;

int fn_ref;

} alien_Callback;

typedef struct _alien_Wrap {

alien_Type tag;

union {

void *p;

int i;

} val;

} alien_Wrap;

typedef union _tagITEM {

ffi_closure closure;

union _tagITEM *next;

} ITEM;

static ITEM *free_list;

int _pagesize;

/* Information to compute strucuture access */

typedef struct { char c; char x; } s_char;

typedef struct { char c; short x; } s_short;

typedef struct { char c; int x; } s_int;

typedef struct { char c; long x; } s_long;

typedef struct { char c; float x; } s_float;

typedef struct { char c; double x; } s_double;

typedef struct { char c; char *x; } s_char_p;

typedef struct { char c; void *x; } s_void_p;

#define AT_CHAR_ALIGN (sizeof(s_char) - sizeof(char))

#define AT_SHORT_ALIGN (sizeof(s_short) - sizeof(short))

#define AT_INT_ALIGN (sizeof(s_int) - sizeof(int))

#define AT_LONG_ALIGN (sizeof(s_long) - sizeof(long))

#define AT_FLOAT_ALIGN (sizeof(s_float) - sizeof(float))

#define AT_DOUBLE_ALIGN (sizeof(s_double) - sizeof(double))

#define AT_CHAR_P_ALIGN (sizeof(s_char_p) - sizeof(char*))

#define AT_VOID_P_ALIGN (sizeof(s_void_p) - sizeof(void*))

static void more_core(void)

{

ITEM *item;

int count, i;

/* determine the pagesize */

#ifdef WINDOWS

if (!_pagesize) {

SYSTEM_INFO systeminfo;

GetSystemInfo(&systeminfo);

_pagesize = systeminfo.dwPageSize;

}

#else

if (!_pagesize) {

_pagesize = getpagesize();

}

#endif

/* calculate the number of nodes to allocate */

count = BLOCKSIZE / sizeof(ITEM);

/* allocate a memory block */

#ifdef WINDOWS

item = (ITEM *)VirtualAlloc(NULL,

count * sizeof(ITEM),

MEM_COMMIT,

PAGE_EXECUTE_READWRITE);

if (item == NULL)

return;

#else

item = (ITEM *)mmap(NULL,

count * sizeof(ITEM),

PROT_READ | PROT_WRITE | PROT_EXEC,

MAP_PRIVATE | MAP_ANONYMOUS,

-1,

0);

if (item == (void *)MAP_FAILED)

return;

#endif

/* put them into the free list */

for (i = 0; i < count; ++i) {

item->next = free_list;

free_list = item;

++item;

}

}

/******************************************************************/

/* put the item back into the free list */

void free_closure(void *p)

{

ITEM *item = (ITEM *)p;

item->next = free_list;

free_list = item;

}

/* return one item from the free list, allocating more if needed */

void *malloc_closure(void)

{

ITEM *item;

if (!free_list)

more_core();

if (!free_list)

return NULL;

item = free_list;

free_list = item->next;

return item;

}

#if defined(LINUX)

#define PLATFORM "linux"

#define USE_DLOPEN

#elif defined(BSD)

#define PLATFORM "bsd"

#define USE_DLOPEN

#elif defined(DARWIN)

#define PLATFORM "darwin"

#define USE_DLOPEN

#endif

#if defined(USE_DLOPEN)

#ifndef RTLD_DEFAULT

#define RTLD_DEFAULT 0

#endif

#include <dlfcn.h>

static void alien_unload (void *lib) {

if(lib && (lib != RTLD_DEFAULT))

dlclose(lib);

}

static void *alien_load (lua_State *L, const char *libname) {

void *lib;

lib = dlopen(libname, RTLD_NOW);

if(lib == NULL) lua_pushstring(L, dlerror());

return lib;

}

static void *alien_loadfunc (lua_State *L, void *lib, const char *sym) {

if(!lib) lib = RTLD_DEFAULT;

void *f = dlsym(lib, sym);

if (f == NULL) lua_pushstring(L, dlerror());

return f;

}

#elif defined(WINDOWS)

#define PLATFORM "windows"

static void pusherror (lua_State *L) {

int error = GetLastError();

char buffer[128];

if (FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM,

NULL, error, 0, buffer, sizeof(buffer), NULL))

lua_pushstring(L, buffer);

else

lua_pushfstring(L, "system error %d\n", error);

}

static void alien_unload (void *lib) {

if(lib)

FreeLibrary((HINSTANCE)lib);

}

static void *alien_load (lua_State *L, const char *libname) {

HINSTANCE lib = LoadLibrary(libname);

if (lib == NULL) pusherror(L);

return lib;

}

static void *alien_loadfunc (lua_State *L, void *lib, const char *sym) {

HINSTANCE module;

void *f;

module = (HINSTANCE)lib;

if(!module) module = GetModuleHandle(NULL);

f = (lua_CFunction)GetProcAddress(module, sym);

if (f == NULL) pusherror(L);

return f;

}

#else

#define DLMSG   "dynamic libraries not enabled; check your Lua installation"

#define PLATFORM "unknown"

static void alien_unload (void *lib) {

(void)lib;  /* to avoid warnings */

}

static void *alien_load (lua_State *L, const char *path) {

(void)path;  /* to avoid warnings */

lua_pushliteral(L, DLMSG);

return NULL;

}

static void *alien_loadfunc (lua_State *L, void *lib, const char *sym) {

(void)lib; (void)sym;  /* to avoid warnings */

lua_pushliteral(L, DLMSG);

return NULL;

}

#endif

#ifndef WINDOWS

#define FFI_STDCALL FFI_DEFAULT_ABI

#endif

#ifdef DARWIN

#define FFI_SYSV FFI_DEFAULT_ABI

#endif

static const ffi_abi ffi_abis[] = { FFI_DEFAULT_ABI, FFI_SYSV, FFI_STDCALL };

static const char *const ffi_abi_names[] = { "default", "cdecl", "stdcall", NULL };

static alien_Library *alien_checklibrary(lua_State *L, int index) {

void *ud = luaL_checkudata(L, index, ALIEN_LIBRARY_META);

luaL_argcheck(L, ud != NULL, index, "alien library expected");

return (alien_Library *)ud;

}

static alien_Function *alien_checkfunction(lua_State *L, int index) {

luaL_getmetatable(L, ALIEN_FUNCTION_META);

lua_getmetatable(L, index);

if(lua_rawequal(L, -1, -2)) {

lua_pop(L, 2);

return (alien_Function *)lua_touserdata(L, index);

}

lua_pop(L, 2);

luaL_getmetatable(L, ALIEN_CALLBACK_META);

lua_getmetatable(L, index);

if(lua_rawequal(L, -1, -2)) {

ffi_closure *ud = *((ffi_closure**)lua_touserdata(L, index));

lua_pop(L, 2);

return (alien_Function *)ud->user_data;

}

lua_pop(L, 2);

luaL_argcheck(L, 0, index, "alien function expected");

return NULL;

}

static ffi_closure *alien_checkcallback(lua_State *L, int index) {

void *ud = luaL_checkudata(L, index, ALIEN_CALLBACK_META);

luaL_argcheck(L, ud != NULL, index, "alien callback expected");

return *((ffi_closure **)ud);

}

static char *alien_checkbuffer(lua_State *L, int index) {

void *ud = luaL_checkudata(L, index, ALIEN_BUFFER_META);

luaL_argcheck(L, ud != NULL, index, "alien buffer expected");

return (char *)ud;

}

static int alien_get(lua_State *L) {

char *name;

const char *libname;

size_t len;

libname = luaL_checklstring(L, lua_gettop(L), &len);

name = (char*)malloc(sizeof(char) * (len + 1));

if(name) {

void *lib;

alien_Library *al;

strcpy(name, libname);

al = (alien_Library *)lua_newuserdata(L, sizeof(alien_Library));

if(!al) luaL_error(L, "out of memory!");

lib = alien_load(L, libname);

if(lib) {

luaL_getmetatable(L, ALIEN_LIBRARY_META);

lua_setmetatable(L, -2);

al->lib = lib;

al->name = name;

return 1;

} else {

lua_error(L);

}

} else {

luaL_error(L, "out of memory!");

}

return 0;

}

static int alien_makefunction(lua_State *L, void *lib, void *fn, char *name) {

alien_Function *af;

af = (alien_Function *)lua_newuserdata(L, sizeof(alien_Function));

if(af) {

luaL_getmetatable(L, ALIEN_FUNCTION_META);

lua_setmetatable(L, -2);

af->fn = fn;

af->name = name;

af->lib = lib;

af->nparams = 0;

af->ret_type = AT_VOID;

af->params = NULL;

} else luaL_error(L, "out of memory!");

return 1;

}

static int alien_library_get(lua_State *L) {

const char *funcname;

char *name;

size_t len;

funcname = luaL_checklstring(L, 2, &len);

lua_getfield(L, lua_upvalueindex(1), funcname);

if(!lua_isnil(L, -1)) return 1;

name = (char*)malloc(sizeof(char) * (len + 1));

if(name) {

alien_Library *al;

void *fn;

strcpy(name, funcname);

al = alien_checklibrary(L, 1);

fn = alien_loadfunc(L, al->lib, funcname);

if(fn) {

alien_makefunction(L, al, fn, name);

lua_pushvalue(L, -1);

lua_setfield(L, lua_upvalueindex(1), funcname);

return 1;

} else {

free(name);

lua_error(L);

}

} else {

luaL_error(L, "out of memory!");

}

return 0;

}

static int alien_function_new(lua_State *L) {

void *fn;

if(lua_isuserdata(L, 1)) {

void *fn = lua_touserdata(L, 1);

return alien_makefunction(L, NULL, fn, NULL);

} else luaL_error(L, "alien: not an userdata");

return 0;

}

static int alien_library_tostring(lua_State *L) {

alien_Library *al;

al = alien_checklibrary(L, 1);

lua_pushfstring(L, "alien library %s", (al->name ? al->name : "default"));

return 1;

}

static void alien_callback_call(ffi_cif *cif, void *resp, void **args, void *data) {

alien_Callback *ac;

int nparams, i;

void *ptr;

ac = (alien_Callback *)data;

lua_rawgeti(ac->L, LUA_REGISTRYINDEX, ac->fn_ref);

//lua_getref(ac->L, ac->fn_ref);

nparams = ac->nparams;

for(i = 0; i < nparams; i++) {

switch(ac->params[i]) {

case AT_BYTE: lua_pushnumber(ac->L, (signed char)*((int*)args[i])); break;

case AT_CHAR: lua_pushnumber(ac->L, (uchar)*((int*)args[i])); break;

case AT_SHORT: lua_pushnumber(ac->L, (short)*((int*)args[i])); break;

case AT_LONG:

lua_pushnumber(ac->L, (long)*((long*)args[i])); break;

case AT_INT: lua_pushnumber(ac->L, *((int*)args[i])); break;

case AT_FLOAT: lua_pushnumber(ac->L, (float)*((float*)args[i])); break;

case AT_DOUBLE: lua_pushnumber(ac->L, *((double*)args[i])); break;

case AT_STRING: lua_pushstring(ac->L, *((char**)args[i])); break;

case AT_REFINT:

lua_pushnumber(ac->L, **((int**)args[i])); break;

case AT_REFCHAR:

lua_pushnumber(ac->L, **((uchar**)args[i])); break;

case AT_REFDOUBLE:

lua_pushnumber(ac->L, **((double**)args[i])); break;

case AT_PTR:

ptr = *((void**)args[i]);

ptr ? lua_pushlightuserdata(ac->L, ptr) : lua_pushnil(ac->L);

break;

default: luaL_error(ac->L, "alien: unknown parameter type in callback");

}

}

lua_call(ac->L, nparams, 1);

switch(ac->ret_type) {

case AT_VOID: break;

case AT_SHORT: *((int*)resp) = (short)lua_tointeger(ac->L, -1); break;

case AT_LONG:

*((long*)resp) = (long)lua_tointeger(ac->L, -1); break;

case AT_INT: *((int*)resp) = (int)lua_tointeger(ac->L, -1); break;

case AT_CHAR: *((int*)resp) = (uchar)lua_tointeger(ac->L, -1); break;

case AT_BYTE: *((int*)resp) = (signed char)lua_tointeger(ac->L, -1); break;

case AT_FLOAT: *((float*)resp) = (float)lua_tonumber(ac->L, -1); break;

case AT_DOUBLE: *((double*)resp) = (double)lua_tonumber(ac->L, -1); break;

case AT_STRING:

if(lua_isuserdata(ac->L, -1))

*((char**)resp) = lua_touserdata(ac->L, -1);

else

*((const char**)resp) = lua_tostring(ac->L, -1);

break;

case AT_PTR:

if(lua_isstring(ac->L, -1))

*((void**)resp) = (void*)lua_tostring(ac->L, -1);

else

*((void**)resp) = lua_touserdata(ac->L, -1);

break;

default: luaL_error(ac->L, "alien: unknown return type in callback");

}

}

static int alien_callback_new(lua_State *L) {

int fn_ref;

alien_Callback *ac;

alien_Type at;

ffi_closure **ud;

int i, nparams;

ffi_status status;

ffi_abi abi;

static ffi_type *const ffitypes[] = {&ffi_type_void, &ffi_type_sint, &ffi_type_double,

&ffi_type_uchar, &ffi_type_pointer, &ffi_type_pointer,

&ffi_type_pointer, &ffi_type_pointer, &ffi_type_pointer,

&ffi_type_pointer, &ffi_type_sshort, &ffi_type_schar,

#ifndef WINDOWS

&ffi_type_slong,

#else

&ffi_type_sint,

#endif

&ffi_type_float};

static int const types[] = {AT_VOID, AT_INT, AT_DOUBLE, AT_CHAR, AT_STRING, AT_PTR, AT_REFINT,

AT_REFDOUBLE, AT_REFCHAR, AT_CALLBACK, AT_SHORT, AT_BYTE, AT_LONG,

AT_FLOAT};

static const char *const typenames[] =

{"void", "int", "double", "char", "string", "pointer",

"ref int", "ref double", "ref char", "callback",

"short", "byte", "long", "float", NULL};

luaL_checktype(L, 1, LUA_TFUNCTION);

if(lua_istable(L, 2)) {

//nparams = lua_objlen(L, 2);

nparams = lua_rawlen(L, 2);

} else {

nparams = lua_gettop(L) - 2;

}

ac = (alien_Callback *)malloc(sizeof(alien_Callback));

ud = (ffi_closure **)lua_newuserdata(L, sizeof(ffi_closure**));

if(ac != NULL && ud != NULL) {

int j;

*ud = malloc_closure();

if(*ud == NULL) { free(ac); luaL_error(L, "alien: cannot allocate callback"); }

ac->L = L;

if(lua_istable(L, 2)) {

lua_getfield(L, 2, "ret");

ac->ret_type = types[luaL_checkoption(L, -1, "int", typenames)];

ac->ffi_ret_type = ffitypes[luaL_checkoption(L, -1, "int", typenames)];

lua_getfield(L, 2, "abi");

abi = ffi_abis[luaL_checkoption(L, -1, "default", ffi_abi_names)];

lua_pop(L, 2);

} else {

ac->ret_type = types[luaL_checkoption(L, 2, "int", typenames)];

ac->ffi_ret_type = ffitypes[luaL_checkoption(L, 2, "int", typenames)];

abi = FFI_DEFAULT_ABI;

}

ac->nparams = nparams;

if(ac->nparams > 0) {

ac->params = (alien_Type *)malloc(ac->nparams * sizeof(alien_Type));

if(!ac->params) luaL_error(L, "alien: out of memory");

ac->ffi_params = (ffi_type **)malloc(ac->nparams * sizeof(ffi_type*));

if(!ac->ffi_params) luaL_error(L, "alien: out of memory");

}

if(lua_istable(L, 2)) {

for(i = 0, j = 1; i < ac->nparams; i++, j++) {

lua_rawgeti(L, 2, j);

ac->ffi_params[i] = ffitypes[luaL_checkoption(L, -1, "int", typenames)];

ac->params[i] = types[luaL_checkoption(L, -1, "int", typenames)];

lua_pop(L, 1);

}

} else {

for(i = 0, j = 3; i < ac->nparams; i++, j++) {

ac->ffi_params[i] = ffitypes[luaL_checkoption(L, j, "int", typenames)];

ac->params[i] = types[luaL_checkoption(L, j, "int", typenames)];

}

}

lua_pushvalue(L, 1);

//ac->fn_ref = lua_ref(L, 1);

ac->fn_ref = luaL_ref(L, 1);

luaL_getmetatable(L, ALIEN_CALLBACK_META);

lua_setmetatable(L, -2);

status = ffi_prep_cif(&(ac->cif), abi, ac->nparams,

ac->ffi_ret_type, ac->ffi_params);

if(status != FFI_OK) luaL_error(L, "alien: cannot create callback");

status = ffi_prep_closure(*ud, &(ac->cif), &alien_callback_call, ac);

ac->fn = *ud;

ac->lib = NULL;

ac->name = NULL;

if(status != FFI_OK) luaL_error(L, "alien: cannot create callback");

return 1;

} else {

if(ac) free(ac);

luaL_error(L, "alien: cannot allocate callback");

}

return 0;

}

static int alien_sizeof(lua_State *L) {

static const int sizes[] = {sizeof(int), sizeof(double), sizeof(uchar),

sizeof(char*), sizeof(void*), sizeof(char),

sizeof(short), sizeof(long), sizeof(float),

sizeof(void*), sizeof(char*), sizeof(int*),

sizeof(double*)};

static const char *const typenames[] = {"int", "double", "char", "string",

"pointer", "byte", "short", "long",

"float", "callback", "ref char",

"ref int", "ref double", NULL};

lua_pushnumber(L, sizes[luaL_checkoption(L, 1, "int", typenames)]);

return 1;

}

static int alien_align(lua_State *L) {

static const int aligns[] = {AT_INT_ALIGN, AT_DOUBLE_ALIGN, AT_CHAR_ALIGN,

AT_CHAR_P_ALIGN, AT_VOID_P_ALIGN, AT_CHAR_ALIGN,

AT_SHORT_ALIGN, AT_LONG_ALIGN, AT_FLOAT_ALIGN,

AT_VOID_P_ALIGN, AT_CHAR_P_ALIGN, AT_VOID_P_ALIGN,

AT_VOID_P_ALIGN};

static const char *const typenames[] = {"int", "double", "char", "string",

"pointer", "byte", "short", "long",

"float", "callback", "ref char",

"ref int", "ref double", NULL};

lua_pushnumber(L, aligns[luaL_checkoption(L, 1, "char", typenames)]);

return 1;

}

static int alien_function_types(lua_State *L) {

static ffi_type* ffitypes[] = {&ffi_type_void, &ffi_type_sint, &ffi_type_double,

&ffi_type_uchar, &ffi_type_pointer, &ffi_type_pointer,

&ffi_type_pointer, &ffi_type_pointer, &ffi_type_pointer,

&ffi_type_pointer, &ffi_type_sshort, &ffi_type_schar,

#ifndef WINDOWS

&ffi_type_slong,

#else

&ffi_type_sint,

#endif

&ffi_type_float};

static const int types[] = {AT_VOID, AT_INT, AT_DOUBLE, AT_CHAR, AT_STRING, AT_PTR, AT_REFINT,

AT_REFDOUBLE, AT_REFCHAR, AT_CALLBACK, AT_SHORT, AT_BYTE, AT_LONG,

AT_FLOAT};

static const char *const typenames[] =

{"void", "int", "double", "char", "string", "pointer",

"ref int", "ref double", "ref char", "callback",

"short", "byte", "long", "float", NULL};

ffi_status status;

ffi_abi abi;

alien_Function *af = alien_checkfunction(L, 1);

int i, j, ret_type;

if(lua_istable(L, 2)) {

lua_getfield(L, 2, "ret");

ret_type = luaL_checkoption(L, -1, "int", typenames);

af->ret_type = types[ret_type];

af->ffi_ret_type = ffitypes[ret_type];

lua_getfield(L, 2, "abi");

abi = ffi_abis[luaL_checkoption(L, -1, "default", ffi_abi_names)];

lua_pop(L, 2);

} else {

ret_type = luaL_checkoption(L, 2, "int", typenames);

af->ret_type = types[ret_type];

af->ffi_ret_type = ffitypes[ret_type];

abi = FFI_DEFAULT_ABI;

}

if(af->params) {

free(af->params); free(af->ffi_params);

af->params = NULL; af->ffi_params = NULL;

}

if(lua_istable(L, 2)) {

//af->nparams = lua_objlen(L, 2);

af->nparams = lua_rawlen(L, 2);

} else {

af->nparams = lua_gettop(L) - 2;

}

if(af->nparams > 0) {

af->ffi_params = (ffi_type **)malloc(sizeof(ffi_type *) * af->nparams);

if(!af->ffi_params) luaL_error(L, "alien: out of memory");

af->params = (alien_Type *)malloc(af->nparams * sizeof(alien_Type));

if(!af->params) luaL_error(L, "alien: out of memory");

}

if(lua_istable(L, 2)) {

for(i = 0, j = 1; i < af->nparams; i++, j++) {

lua_rawgeti(L, 2, j);

af->ffi_params[i] = ffitypes[luaL_checkoption(L, -1, "int", typenames)];

af->params[i] = types[luaL_checkoption(L, -1, "int", typenames)];

lua_pop(L, 1);

}

} else {

for(i = 0, j = 3; i < af->nparams; i++, j++) {

int type = luaL_checkoption(L, j, "int", typenames);

af->ffi_params[i] = ffitypes[type];

af->params[i] = types[type];

}

}

status = ffi_prep_cif(&(af->cif), abi, af->nparams,

af->ffi_ret_type,

af->ffi_params);

if(status != FFI_OK)

luaL_error(L, "alien: error in libffi preparation");

return 0;

}

static int alien_function_tostring(lua_State *L) {

alien_Function*af;

af = alien_checkfunction(L, 1);

lua_pushfstring(L, "alien function %s, library %s", af->name ? af->name : "anonymous",

((af->lib && af->lib->name) ? af->lib->name : "default"));

return 1;

}

static int alien_function_call(lua_State *L) {

int i, j, nargs, nparams;

int iret; double dret; void *pret; long lret; float fret;

int *refi_args = NULL;

int nrefi, nrefd, nrefc;

double *refd_args =NULL;

char *refc_args = NULL;

void **args = NULL;

ffi_cif *cif;

alien_Function *af = alien_checkfunction(L, 1);

cif = &(af->cif);

nparams = af->nparams;

nargs = lua_gettop(L) - 1;

if(nargs < nparams)

luaL_error(L, "alien: too few arguments (function %s)", af->name ?

af->name : "anonymous");

else if(nargs > nparams)

luaL_error(L, "alien: too many arguments (function %s)", af->name ?

af->name : "anonymous");

for(i = 0, nrefi = 0, nrefd = 0, nrefc = 0; i < nparams; i++) {

switch(af->params[i]) {

case AT_REFINT: nrefi++; break;

case AT_REFDOUBLE: nrefd++; break;

case AT_REFCHAR: nrefc++; break;

}

}

if(nrefi > 0) refi_args = (int*)ALLOCA(sizeof(int) * nrefi);

if(nrefd > 0) refd_args = (double*)ALLOCA(sizeof(double) * nrefd);

if(nrefc > 0) refc_args = (char*)ALLOCA(sizeof(char) * nrefc);

if(nargs > 0) args = ALLOCA(sizeof(void*) * nargs);

for(i = 0, j = 2; i < nparams; i++, j++) {

void *arg;

switch(af->params[i]) {

case AT_SHORT:

arg = ALLOCA(sizeof(short)); *((short*)arg) = (short)lua_tointeger(L, j);

args[i] = arg; break;

case AT_LONG:

arg = ALLOCA(sizeof(long)); *((long*)arg) = (long)lua_tointeger(L, j);

args[i] = arg; break;

case AT_INT:

arg = ALLOCA(sizeof(int)); *((int*)arg) = (int)lua_tointeger(L, j);

args[i] = arg; break;

case AT_CHAR:

arg = ALLOCA(sizeof(uchar)); *((uchar*)arg) = (uchar)lua_tointeger(L, j);

args[i] = arg; break;

case AT_BYTE:

arg = ALLOCA(sizeof(char)); *((char*)arg) = (signed char)lua_tointeger(L, j);

args[i] = arg; break;

case AT_FLOAT:

arg = ALLOCA(sizeof(float)); *((float*)arg) = (float)lua_tonumber(L, j);

args[i] = arg; break;

case AT_DOUBLE:

arg = ALLOCA(sizeof(double)); *((double*)arg) = (double)lua_tonumber(L, j);

args[i] = arg; break;

case AT_STRING:

arg = ALLOCA(sizeof(char*));

if(lua_isuserdata(L, j))

*((char**)arg) = lua_isnil(L, j) ? NULL : lua_touserdata(L, j);

else

*((const char**)arg) = lua_isnil(L, j) ? NULL : lua_tostring(L, j);

args[i] = arg;

break;

case AT_CALLBACK:

arg = ALLOCA(sizeof(void*));

*((void**)arg) = alien_checkcallback(L, j);

args[i] = arg;

break;

case AT_PTR:

arg = ALLOCA(sizeof(char*));

*((void**)arg) = lua_isnil(L, j) ? NULL :

(lua_isstring(L, j) ? (void*)lua_tostring(L, j) :

lua_touserdata(L, j));

args[i] = arg;

break;

case AT_REFINT:

*refi_args = (int)lua_tointeger(L, j);

arg = ALLOCA(sizeof(int*));

*((int**)arg) = refi_args;

args[i] = arg; refi_args++; break;

break;

case AT_REFCHAR:

*refc_args = (char)lua_tointeger(L, j);

arg = ALLOCA(sizeof(char*));

*((char**)arg) = refc_args;

args[i] = arg; refc_args++; break;

break;

case AT_REFDOUBLE:

*refd_args = lua_tonumber(L, j);

arg = ALLOCA(sizeof(double*));

*((double**)arg) = refd_args;

args[i] = arg; refd_args++; break;

break;

default:

luaL_error(L, "alien: parameter %i is of unknown type (function %s)", j,

af->name ? af->name : "anonymous");

}

}

pret = NULL;

switch(af->ret_type) {

case AT_VOID: ffi_call(cif, af->fn, NULL, args); lua_pushnil(L); break;

case AT_SHORT: ffi_call(cif, af->fn, &iret, args); lua_pushnumber(L, (short)iret); break;

case AT_LONG:

ffi_call(cif, af->fn, &lret, args); lua_pushnumber(L, lret); break;

case AT_INT: ffi_call(cif, af->fn, &iret, args); lua_pushnumber(L, iret); break;

case AT_CHAR: ffi_call(cif, af->fn, &iret, args); lua_pushnumber(L, (uchar)iret); break;

case AT_BYTE: ffi_call(cif, af->fn, &iret, args); lua_pushnumber(L, (signed char)iret); break;

case AT_FLOAT: ffi_call(cif, af->fn, &fret, args); lua_pushnumber(L, fret); break;

case AT_DOUBLE: ffi_call(cif, af->fn, &dret, args); lua_pushnumber(L, dret); break;

case AT_STRING: ffi_call(cif, af->fn, &pret, args);

if (pret)

{

lua_pushstring(L, (const char *)pret);

}

else

{

lua_pushnil(L);

}

break;

case AT_PTR: ffi_call(cif, af->fn, &pret, args);

(pret ? lua_pushlightuserdata(L, pret) : lua_pushnil(L)); break;

default:

luaL_error(L, "alien: unknown return type (function %s)", af->name ?

af->name : "anonymous");

}

refi_args -= nrefi; refd_args -= nrefd; refc_args -= nrefc;

for(i = 0; i < nparams; i++) {

switch(af->params[i]) {

case AT_REFINT: lua_pushnumber(L, *refi_args); refi_args++; break;

case AT_REFDOUBLE: lua_pushnumber(L, *refd_args); refd_args++; break;

case AT_REFCHAR: lua_pushnumber(L, *refc_args); refc_args++; break;

}

}

return 1 + nrefi + nrefc + nrefd;

}

static int alien_library_gc(lua_State *L) {

alien_Library *al = alien_checklibrary(L, 1);

if(al->lib) {

alien_unload(al->lib);

if(al->name) free(al->name);

}

return 0;

}

static int alien_function_gc(lua_State *L) {

alien_Function *af = alien_checkfunction(L, 1);

if(af->name) free(af->name);

if(af->params) free(af->params);

if(af->ffi_params) free(af->ffi_params);

return 0;

}

static int alien_callback_gc(lua_State *L) {

ffi_closure *ud = alien_checkcallback(L, 1);

alien_Callback *ac = (alien_Callback *)ud->user_data;

//lua_unref(ac->L, ac->fn_ref);

luaL_unref(ac->L, LUA_REGISTRYINDEX, ac->fn_ref);

if(ac->params) free(ac->params);

if(ac->ffi_params) free(ac->ffi_params);

free_closure(ud);

return 0;

}

static int alien_register(lua_State *L) {

const char *meta = luaL_checkstring(L, 1);

luaL_getmetatable(L, meta);

if(lua_isnil(L, -1))

luaL_newmetatable(L, meta);

return 1;

}

static int alien_pack(lua_State *L) {

int i, top;

alien_Wrap *ud;

const char *meta = luaL_checkstring(L, 1);

ud = (alien_Wrap*)lua_newuserdata(L, sizeof(alien_Wrap) * lua_gettop(L));

top = lua_gettop(L);

for(i = 2; i < top ; i++) {

if(lua_isnil(L, i)) {

ud[i - 2].tag = AT_PTR;

ud[i - 2].val.p = NULL;

}

else if(lua_isuserdata(L, i)) {

ud[i - 2].tag = AT_PTR;

ud[i - 2].val.p = lua_touserdata(L, i);

} else {

ud[i - 2].tag = AT_INT;

ud[i - 2].val.i = lua_tointeger(L, i);

}

}

ud[lua_gettop(L) - 2].tag = AT_VOID;

luaL_getmetatable(L, meta);

lua_setmetatable(L, -2);

return 1;

}

static int alien_unpack(lua_State *L) {

int size, i;

alien_Wrap *ud;

const char *meta = luaL_checkstring(L, 1);

ud = (alien_Wrap *)luaL_checkudata(L, 2, meta);

luaL_argcheck(L, ud != NULL, 2, "userdata has wrong metatable");

while(ud->tag != AT_VOID) {

switch(ud->tag) {

case AT_INT: lua_pushnumber(L, ud->val.i); break;

case AT_PTR: ud->val.p ? lua_pushlightuserdata(L, ud->val.p) :

lua_pushnil(L); break;

default: luaL_error(L, "wrong type in wrapped value");

}

ud++;

}

return lua_gettop(L) - 2;

}

static int alien_repack(lua_State *L) {

int size, i, top;

alien_Wrap *ud;

const char *meta = luaL_checkstring(L, 1);

ud = (alien_Wrap *)luaL_checkudata(L, 2, meta);

i = 3;

top = lua_gettop(L);

while(ud->tag != AT_VOID) {

if(i > top || lua_isnil(L, i)) {

ud->tag = AT_PTR;

ud->val.p = NULL;

}

else if(lua_isuserdata(L, i)) {

ud->tag = AT_PTR;

ud->val.p = lua_touserdata(L, i);

} else {

ud->tag = AT_INT;

ud->val.i = lua_tointeger(L, i);

}

ud++; i++;

}

return 0;

}

static int alien_buffer_new(lua_State *L) {

const char *s; char *b;

size_t size;

if(lua_type(L, 1) == LUA_TSTRING) {

s = lua_tolstring(L, 1, &size);

size++;

} else if(lua_type(L, 1) == LUA_TLIGHTUSERDATA) {

luaL_getmetatable(L, ALIEN_BUFFER_META);

lua_setmetatable(L, -2);

return 1;

} else {

s = NULL;

//size = luaL_optint(L, 1, BUFSIZ);

size = luaL_optinteger(L, 1, BUFSIZ);

}

b = (char *)lua_newuserdata(L, size);

if(b) {

if(s) {

memcpy(b, s, size - 1);

b[size - 1] = ‘\0‘;

}

luaL_getmetatable(L, ALIEN_BUFFER_META);

lua_setmetatable(L, -2);

return 1;

} else {

luaL_error(L, "cannot allocate buffer");

}

return 0;

}

static int alien_buffer_tostring(lua_State *L) {

char *b;

int size;

b = alien_checkbuffer(L, 1);

if(lua_gettop(L) < 2 || lua_isnil(L, 2))

size = strlen(b);

else

size = luaL_checkinteger(L, 2);

lua_pushlstring(L, b, size);

return 1;

}

static int alien_buffer_len(lua_State *L) {

char *b = alien_checkbuffer(L, 1);

lua_pushinteger(L, strlen(b));

return 1;

}

static int alien_buffer_topointer(lua_State *L) {

char *b = alien_checkbuffer(L, 1);

lua_pushlightuserdata(L, b);

return 1;

}

static int alien_buffer_put(lua_State *L);

static int alien_buffer_get(lua_State *L) {

static const void* funcs[] = {&alien_buffer_tostring,

&alien_buffer_topointer,

&alien_buffer_len,

&alien_buffer_get,

&alien_buffer_put};

static const char *const funcnames[] = { "tostring", "topointer", "len", "get", "set", NULL };

static const int types[] = {AT_VOID, AT_INT, AT_DOUBLE, AT_CHAR, AT_STRING, AT_PTR, AT_REFINT,

AT_REFDOUBLE, AT_REFCHAR, AT_CALLBACK, AT_SHORT, AT_BYTE, AT_LONG,

AT_FLOAT};

static const char *const typenames[] =

{"void", "int", "double", "char", "string", "pointer",

"ref int", "ref double", "ref char", "callback",

"short", "byte", "long", "float", NULL};

char *b = alien_checkbuffer(L, 1);

if(lua_type(L, 2) == LUA_TSTRING) {

lua_pushcfunction(L,

(lua_CFunction)funcs[luaL_checkoption(L, 2, "tostring", funcnames)]);

} else {

void *p;

int offset = luaL_checkinteger(L, 2) - 1;

int type = types[luaL_checkoption(L, 3, "char", typenames)];

switch(type) {

case AT_SHORT: lua_pushnumber(L, *((short*)(&b[offset]))); break;

case AT_INT: lua_pushnumber(L, *((int*)(&b[offset]))); break;

case AT_LONG: lua_pushnumber(L, *((long*)(&b[offset]))); break;

case AT_BYTE: lua_pushnumber(L, (signed char)b[offset]); break;

case AT_CHAR: lua_pushnumber(L, b[offset]); break;

case AT_FLOAT: lua_pushnumber(L, *((float*)(&b[offset]))); break;

case AT_DOUBLE: lua_pushnumber(L, *((double*)(&b[offset]))); break;

case AT_STRING:

p = *((void**)&b[offset]);

if (p)

{

lua_pushstring(L, (char*)p);

}

else

{

lua_pushnil(L);

}

break;

case AT_CALLBACK:

p = *((void**)&b[offset]);

p ? alien_makefunction(L, NULL, p, NULL) : lua_pushnil(L);

break;

case AT_PTR:

p = *((void**)&b[offset]);

p ? lua_pushlightuserdata(L, p) : lua_pushnil(L);

break;

default:

luaL_error(L, "alien: unknown type in buffer:get");

}

}

return 1;

}

static int alien_buffer_put(lua_State *L) {

static const int types[] = {AT_VOID, AT_INT, AT_DOUBLE, AT_CHAR, AT_STRING, AT_PTR, AT_REFINT,

AT_REFDOUBLE, AT_REFCHAR, AT_CALLBACK, AT_SHORT, AT_BYTE, AT_LONG,

AT_FLOAT};

static const char *const typenames[] =

{"void", "int", "double", "char", "string", "pointer",

"ref int", "ref double", "ref char", "callback",

"short", "byte", "long", "float", NULL};

char *b = alien_checkbuffer(L, 1);

int offset = luaL_checkinteger(L, 2) - 1;

int type = types[luaL_checkoption(L, 4, "char", typenames)];

switch(type) {

case AT_SHORT: *((short*)(&b[offset])) = (short)lua_tointeger(L, 3); break;

case AT_INT: *((int*)(&b[offset])) = (int)lua_tointeger(L, 3); break;

case AT_LONG: *((long*)(&b[offset])) = (long)lua_tointeger(L, 3); break;

case AT_BYTE: b[offset] = (signed char)lua_tointeger(L, 3); break;

case AT_CHAR: b[offset] = (char)lua_tointeger(L, 3); break;

case AT_FLOAT: *((float*)(&b[offset])) = (float)lua_tonumber(L, 3); break;

case AT_DOUBLE: *((double*)(&b[offset])) = (double)lua_tonumber(L, 3); break;

case AT_STRING: *((char**)(&b[offset])) =

(lua_isnil(L, 3) ? NULL : (char*)lua_tostring(L, 3)); break;

case AT_CALLBACK: *((void**)(&b[offset])) = alien_checkcallback(L, 3); break;

case AT_PTR: *((void**)(&b[offset])) =

(lua_isnil(L, 3) ? NULL : (lua_isuserdata(L, 3) ? lua_touserdata(L, 3) :

(void*)lua_tostring(L, 3))); break;

default:

luaL_error(L, "alien: unknown type in buffer:put");

}

return 0;

}

static int alien_register_library_meta(lua_State *L) {

luaL_newmetatable(L, ALIEN_LIBRARY_META);

lua_pushliteral(L, "__gc");

lua_pushcfunction(L, alien_library_gc);

lua_settable(L, -3);

lua_pushliteral(L, "__tostring");

lua_pushcfunction(L, alien_library_tostring);

lua_settable(L, -3);

lua_pushliteral(L, "__index");

lua_newtable(L);

lua_pushcclosure(L, alien_library_get, 1);

lua_settable(L, -3);

lua_pop(L, 1);

return 0;

}

static int alien_register_callback_meta(lua_State *L) {

luaL_newmetatable(L, ALIEN_CALLBACK_META);

lua_pushliteral(L, "__call");

lua_pushcfunction(L, alien_function_call);

lua_settable(L, -3);

lua_pushliteral(L, "__gc");

lua_pushcfunction(L, alien_callback_gc);

lua_settable(L, -3);

lua_pushliteral(L, "__tostring");

lua_pushcfunction(L, alien_function_tostring);

lua_settable(L, -3);

lua_pop(L, 1);

return 0;

}

static int alien_register_function_meta(lua_State *L) {

luaL_newmetatable(L, ALIEN_FUNCTION_META);

lua_pushliteral(L, "__index");

lua_newtable(L);

lua_pushliteral(L, "types");

lua_pushcfunction(L, alien_function_types);

lua_settable(L, -3);

lua_settable(L, -3);

lua_pushliteral(L, "__call");

lua_pushcfunction(L, alien_function_call);

lua_settable(L, -3);

lua_pushliteral(L, "__gc");

lua_pushcfunction(L, alien_function_gc);

lua_settable(L, -3);

lua_pushliteral(L, "__tostring");

lua_pushcfunction(L, alien_function_tostring);

lua_settable(L, -3);

lua_pop(L, 1);

return 0;

}

static int alien_register_buffer_meta(lua_State *L) {

luaL_newmetatable(L, ALIEN_BUFFER_META);

lua_pushliteral(L, "__index");

lua_pushcfunction(L, alien_buffer_get);

lua_settable(L, -3);

lua_pushliteral(L, "__newindex");

lua_pushcfunction(L, alien_buffer_put);

lua_settable(L, -3);

lua_pushliteral(L, "__tostring");

lua_pushcfunction(L, alien_buffer_tostring);

lua_settable(L, -3);

lua_pop(L, 1);

return 0;

}

static int alien_errno(lua_State *L) {

lua_pushnumber(L, errno);

return 1;

}

static int alien_udata2str(lua_State *L) {

char *ud;

int size;

if(lua_isnil(L, 1)) {

lua_pushnil(L);

return 1;

}

luaL_checktype(L, 1, LUA_TLIGHTUSERDATA);

ud = (char *)lua_touserdata(L, 1);

if(lua_gettop(L) < 2 || lua_isnil(L, 2))

size = strlen(ud);

else

size = luaL_checkinteger(L, 2);

lua_pushlstring(L, ud, size);

return 1;

}

static int alien_udata2double(lua_State *L) {

double *ud;

int size, i;

if(lua_isnil(L, 1)) {

lua_pushnil(L);

return 1;

}

luaL_checktype(L, 1, LUA_TLIGHTUSERDATA);

if(lua_gettop(L) < 2 || lua_isnil(L, 2))

size = 1;

else

size = luaL_checkinteger(L, 2);

ud = (double *)lua_touserdata(L, 1);

for(i = 0; i < size; i++)

lua_pushnumber(L, ud[i]);

return size;

}

static int alien_udata2int(lua_State *L) {

int *ud;

int size, i;

if(lua_isnil(L, 1)) {

lua_pushnil(L);

return 1;

}

luaL_checktype(L, 1, LUA_TLIGHTUSERDATA);

if(lua_gettop(L) < 2 || lua_isnil(L, 2))

size = 1;

else

size = luaL_checkinteger(L, 2);

ud = (int *)lua_touserdata(L, 1);

for(i = 0; i < size; i++) {

lua_pushnumber(L, ud[i]);

}

return size;

}

static int alien_udata2short(lua_State *L) {

short *ud;

int size, i;

if(lua_isnil(L, 1)) {

lua_pushnil(L);

return 1;

}

luaL_checktype(L, 1, LUA_TLIGHTUSERDATA);

if(lua_gettop(L) < 2 || lua_isnil(L, 2))

size = 1;

else

size = luaL_checkinteger(L, 2);

ud = (short *)lua_touserdata(L, 1);

for(i = 0; i < size; i++)

lua_pushnumber(L, ud[i]);

return size;

}

static int alien_udata2char(lua_State *L) {

char *ud;

int size, i;

if(lua_isnil(L, 1)) {

lua_pushnil(L);

return 1;

}

luaL_checktype(L, 1, LUA_TLIGHTUSERDATA);

if(lua_gettop(L) < 2 || lua_isnil(L, 2))

size = 1;

else

size = luaL_checkinteger(L, 2);

ud = (char *)lua_touserdata(L, 1);

for(i = 0; i < size; i++)

lua_pushnumber(L, ud[i]);

return size;

}

static int alien_udata2long(lua_State *L) {

long *ud;

int size, i;

if(lua_isnil(L, 1)) {

lua_pushnil(L);

return 1;

}

luaL_checktype(L, 1, LUA_TLIGHTUSERDATA);

if(lua_gettop(L) < 2 || lua_isnil(L, 2))

size = 1;

else

size = luaL_checkinteger(L, 2);

ud = (long *)lua_touserdata(L, 1);

for(i = 0; i < size; i++)

lua_pushnumber(L, ud[i]);

return size;

}

static int alien_udata2float(lua_State *L) {

float *ud;

int size, i;

if(lua_isnil(L, 1)) {

lua_pushnil(L);

return 1;

}

luaL_checktype(L, 1, LUA_TLIGHTUSERDATA);

if(lua_gettop(L) < 2 || lua_isnil(L, 2))

size = 1;

else

size = luaL_checkinteger(L, 2);

ud = (float *)lua_touserdata(L, 1);

for(i = 0; i < size; i++)

lua_pushnumber(L, ud[i]);

return size;

}

static int alien_isnull(lua_State *L) {

void *ud;

luaL_checktype(L, 1, LUA_TLIGHTUSERDATA);

ud = lua_touserdata(L, 1);

lua_pushboolean(L, ud == NULL);

return 1;

}

static int alien_table_new(lua_State *L) {

int narray, nhash;

//narray = luaL_optint(L, 1, 0);

//nhash = luaL_optint(L, 2, 0);

narray = luaL_optinteger(L, 1, 0);

nhash = luaL_optinteger(L, 2, 0);

lua_createtable(L, narray, nhash);

return 1;

}

static const struct luaL_Reg alienlib[] = {

{"load", alien_get},

{"align", alien_align},

{"tag", alien_register},

{"wrap", alien_pack},

{"rewrap", alien_repack},

{"unwrap", alien_unpack},

{"errno", alien_errno},

{"tostring", alien_udata2str},

{"isnull", alien_isnull},

{"sizeof", alien_sizeof},

{"todouble", alien_udata2double},

{"toint", alien_udata2int},

{"tolong", alien_udata2long},

{"tofloat", alien_udata2float},

{"toshort", alien_udata2short},

{"tochar", alien_udata2char},

{"buffer", alien_buffer_new},

{"callback", alien_callback_new},

{"funcptr", alien_function_new},

{"table", alien_table_new},

{NULL, NULL},

};

static int alien_register_main(lua_State *L) {

alien_Library *al;

luaL_newlib(L, alienlib);

lua_pushliteral(L, PLATFORM);

lua_setfield(L, -2, "platform");

al = (alien_Library *)lua_newuserdata(L, sizeof(alien_Library));

al->lib = NULL;

al->name = "default";

luaL_getmetatable(L, ALIEN_LIBRARY_META);

lua_setmetatable(L, -2);

lua_setfield(L, -2, "default");

return 1;

}

__declspec(dllexport) int luaopen_alien(lua_State *L) {

alien_register_library_meta(L);

alien_register_callback_meta(L);

alien_register_function_meta(L);

alien_register_buffer_meta(L);

lua_getglobal(L, "alien");

if(lua_isnil(L, -1)) {

lua_newtable(L);

lua_pushvalue(L, -1);

lua_setglobal(L, "alien");

}

lua_newtable(L);

lua_pushvalue(L, -1);

lua_setfield(L, -3, "core");

alien_register_main(L);

return 1;

}

时间: 2024-10-01 02:39:02

改写 alien core使其可以适配lua5.3的相关文章

改写 alien struct使其适配lua5.3

/* ** Library for packing/unpacking structures. ** ** Valid formats: ** x - pading ** b/B - signed/unsigned byte ** h/H - signed/unsigned short ** l/L - signed/unsigned long ** i/In - signed/unsigned integer with size `n' (default is size of int) **

[Xcode10 实际操作]九、实用进阶-(25)使用Storyboard(故事版)的约束功能,使项目快速适配各种分辨率的设备

本文将演示使用故事版的约束功能,使项目快速适配各种分辨率的设备. 在项目导航区打开并编辑主故事版[Main.storyboard]. 在当前故事版中,已经存在一个适配4寸屏幕的界面, 点击设备名称,更改设备类型.在弹出的模拟器列表中,选择一款拥有4.7寸屏幕的模拟器. 然后通过系统提供的约束功能,对各尺寸屏幕进行适配. 在故事版文档框架区中的[View Controller],点击显示[MainView]视图下的所有子元素. 该视图是添加的自定义视图,尺寸与根视图相同,并且包含了页面中的所有元素

条目四十:若一个类是函数子,使它可适配

<条目四十:若一个类是函数子,使它可适配> 在stl中,下面的函数适配器可以使函数指针转换为特定的类型,供下面的使用. 4个标准的函数配接器(not1.not2.bind1st和bind2nd)都要求一些特殊的类型定义,那些非标准的.与STL兼容的配接器通常也是如此. 但是如果是函数对象,那么需要继承基类函数适配器,实现特定的接口,使函数子拥有可适配的特性,这样才能更加健壮,适用范围更广. 如果函数子类的operator()只有一个实参,那么它应该从std::unary_function继承:

.Net Core小技巧 - Swagger适配虚拟目录及二级目录

前言 随着前后端分离模式与微服务架构的出现,Web API变得越来越重要及普遍.而后出现的网关技术,使开发者更倾向于使用二级/多级目录来暴露Web API,一是暴露的端口更少,方便管理:二是在网关中可以处理一些公共的事务,如认证.但swagger默认是适配根(root)目录的,想要适配二级/多级目录,需要额外处理,同时还要区分开发环境与其它环境.一种思路是在开发环境就让Web API是处于二级目录,此时可以在本机通过nginx和iis虚拟目录来模拟,但这种思路明显略微麻烦.另一种思路是通过配置多

exists改写SQL,使其走正确的执行计划

数据库环境:SQL SERVER 2005 今天看到一条SQL,写得不是很复杂,返回7000多条数据,却执行了15s.SQL文本及各表的数据量如下: SELECT acinv_07.id_item , SUM(acinv_07.dec_endqty) dec_endqty FROM acinv_07 WHERE acinv_07.fiscal_year * 100 + acinv_07.fiscal_period = ( SELECT DISTINCT ctlm1101.fiscal_year

CSS——&lt;img&gt;标签图片适配居中问题

图片标签为<img>,为单闭合标签,使用时<img src="./im.png" alt="花"/> 必选属性: alt    图像的替代文本 src   规定显示图像的URL img属于行内替换元素,可以使用height/width/padding/margin均可以使用,效果等效于块元素.如果设定了width但未设置height,那么img的height会根据比例缩放. 如何让图片在div中居中显示? 1.对div使用text-align

NET Core 介绍

NET Core 介绍 1. 前言 2. ASP.NET Core 简介 2.1 什么是ASP.NET Core 2.2 ASP.NET Core的特点 2.3 ASP.NET Core 项目文件夹解读 2.3.1 项目文件夹总览 2.3.2 project.json和global.json 2.3.1 Properties——launchSettings.json 2.3.4 Startup.cs (1) 构造函数 (2) ConfigureServices (3) Configure 2.3

android API Guides 之 web app -------------Targeting Screens from Web Apps(屏幕适配)

如果你在Android设备上设计开发一款web应用,你就应该考虑web页面在不同屏幕上的显示问题.因为Android有很多不同类型的手机屏幕,所以你应该去考虑那些影响web页面在Android设备上显示的因素. 注意:本文中描述的以下特性,已经在Android 2.0或更高的版本中的Android浏览器(Android系统默认的)和WebView(Android中用于显示网页的控件)上得到支持.第三方的浏览器可能不支持这些的属性.(也就是说只做了解) 针对web页面适配Android设备,你应该

移动端屏幕适配解决方案

因原在做移动端适配过程中,一直都是应用淘宝的flexible高清方案解决,也没有认真的去研究过源码.这几天又看到一些普通的适配方案,于是把两者源码放在一起比较,发现高清方案是通过动态的获取了当前设备的dpr值,然后根据dpr值的大小来设定手机的视口的缩放比例,从而实现高清.比如:dpr=2时,设定initial-scale = 0.5 ;  dpr=3时 ,设定initial-scale = 0.333 : 一.手机端viewport详解 <meta name="viewport"