LuaEngine v0.3

This commit is contained in:
Kirigaya Kazuto 2020-05-29 01:39:49 +08:00
parent 3abf10ed2b
commit 71059fda47
12 changed files with 541 additions and 105 deletions

View File

@ -11,8 +11,10 @@ void InitLuaEngine(lua_State* L)
InitMusic(L); InitMusic(L);
InitCommon(L); InitCommon(L);
InitTCPSocket(L); InitTCPSocket(L);
InitThread(L); InitUDPSocket(L);
InitNetwork(L);
InitSocketSelector(L); InitSocketSelector(L);
InitThread(L);
} }
void InitEngine() void InitEngine()
@ -26,7 +28,7 @@ void InitEngine()
SDL_Log("Mix_OpenAudio: %s\n", Mix_GetError()); SDL_Log("Mix_OpenAudio: %s\n", Mix_GetError());
exit(2); exit(2);
} }
Mix_AllocateChannels(16);
// Stop text input event // Stop text input event
SDL_StopTextInput(); SDL_StopTextInput();

View File

@ -4,7 +4,8 @@
module Music module Music
load(filename: string): MusicMedia load(filename: string): MusicMedia
loadChunk(filename: string): ChunkMedia loadChunk(filename: string): ChunkMedia
play(music: MusicMedia, [loops: int]) play(music: MusicMedia, [loops: int]) Loops default to 1 time
playChunk(chunk: ChunkMedia, channel: int, [loops: int]) Loops default to 1 time.
pause() pause()
resume() resume()
*/ */
@ -106,7 +107,7 @@ int music_loadchunkmem(lua_State* L)
int music_play(lua_State* L) int music_play(lua_State* L)
{ {
auto music = lua_checkpointer<Mix_Music>(L, 1, "LuaEngineMusicMedia"); auto music = lua_checkpointer<Mix_Music>(L, 1, "LuaEngineMusicMedia");
int loops = -1; int loops = 0;
if (!lua_isnone(L, 2)) if (!lua_isnone(L, 2))
{ {
loops = luaL_checkinteger(L, 2); loops = luaL_checkinteger(L, 2);
@ -118,6 +119,24 @@ int music_play(lua_State* L)
return 0; return 0;
} }
int music_playchunk(lua_State* L)
{
auto chunk = lua_checkpointer<Mix_Chunk>(L, 1, "LuaEngineChunkMedia");
int channel = luaL_checkinteger(L, 2);
int loops = 0;
if (!lua_isnone(L, 3))
{
loops = luaL_checkinteger(L, 3);
}
int ret = Mix_PlayChannel(channel, chunk, loops);
if (ret == -1)
{
return MixError(L, Mix_PlayChannel);
}
lua_pushinteger(L, ret);
return 1;
}
int music_pause(lua_State* L) int music_pause(lua_State* L)
{ {
Mix_PauseMusic(); Mix_PauseMusic();
@ -140,6 +159,7 @@ void InitMusic(lua_State* L)
lua_setfield_function(L, "loadChunk", music_loadchunk); lua_setfield_function(L, "loadChunk", music_loadchunk);
lua_setfield_function(L, "loadChunkmem", music_loadchunkmem); lua_setfield_function(L, "loadChunkmem", music_loadchunkmem);
lua_setfield_function(L, "play", music_play); lua_setfield_function(L, "play", music_play);
lua_setfield_function(L, "playChunk", music_playchunk);
lua_setfield_function(L, "pause", music_pause); lua_setfield_function(L, "pause", music_pause);
lua_setfield_function(L, "resume", music_resume); lua_setfield_function(L, "resume", music_resume);
lua_setfield(L, -2, "Music"); lua_setfield(L, -2, "Music");

57
NetworkWin.cpp Normal file
View File

@ -0,0 +1,57 @@
#include "include.h"
#ifdef _WIN32
#define _WIN32_WINNT 0x0A00 // Win10
#include <winsock2.h>
#include <ws2tcpip.h>
int network_getip(lua_State* L)
{
const char* host = luaL_checkstring(L, 1);
addrinfo* result = NULL;
if (getaddrinfo(host, NULL, NULL, &result) < 0)
{
int errcode = WSAGetLastError();
put_winerror(L, errcode, "getaddrinfo");
return lua_error(L);
}
int cnt = 0;
for (addrinfo* pinfo = result; pinfo; pinfo = pinfo->ai_next)
{
switch (pinfo->ai_family)
{
case AF_INET:
{
char buffer[1024] = { 0 };
if (inet_ntop(AF_INET, &((sockaddr_in*)(pinfo->ai_addr))->sin_addr, buffer, 1024))
{
int errcode = WSAGetLastError();
put_winerror(L, errcode, "inet_ntop");
freeaddrinfo(result);
return lua_error(L);
}
lua_pushstring(L, buffer);
cnt++;
break;
}
}
}
freeaddrinfo(result);
return cnt;
}
void InitNetwork(lua_State* L)
{
lua_getglobal(L, "package");
lua_getfield(L, -1, "loaded");
lua_newtable(L);
lua_setfield_function(L, "getip", network_getip);
lua_setfield(L, -2, "network");
lua_pop(L, 2);
}
#endif // End of _WIN32

View File

@ -1,5 +1,5 @@
#include "Select.h" #include "Select.h"
#include "TCP.h" #include "Socket.h"
#ifdef _WIN32 #ifdef _WIN32
#define _WIN32_WINNT 0x0A00 // Win10 #define _WIN32_WINNT 0x0A00 // Win10
@ -8,57 +8,59 @@
#include <vector> #include <vector>
using namespace std; using namespace std;
inline void luatable_to_fdset(lua_State* L, int tbl_index, fd_set& fds)
{
lua_pushnil(L);
while (lua_next(L, tbl_index))
{
lua_pop(L, 1);
auto s = lua_testblock<SocketData>(L, -1, "LuaEngineTCPSocket") ? lua_checkblock<SocketData>(L, -1, "LuaEngineTCPSocket") : lua_checkblock<SocketData>(L, -1, "LuaEngineUDPSocket");
if (s->fd > 0)
{
FD_SET(s->fd, &fds);
}
}
}
inline void fdset_to_luatable(lua_State* L, int tbl_index, fd_set& fds)
{
lua_newtable(L); // ... RetT
lua_pushnil(L); // ... RetT nil
while (lua_next(L, tbl_index))
{
lua_pop(L, 1); // ... RetT Socket
auto s = lua_testblock<SocketData>(L, -1, "LuaEngineTCPSocket") ? lua_checkblock<SocketData>(L, -1, "LuaEngineTCPSocket") : lua_checkblock<SocketData>(L, -1, "LuaEngineUDPSocket");
if (s->fd > 0 && FD_ISSET(s->fd, &fds))
{
lua_pushvalue(L, -1); // ... RetT Socket Socket
lua_pushboolean(L, true); // ... RetT Socket Socket true
lua_settable(L, -4); // ... RetT Socket
}
}
}
int select_call(lua_State* L) int select_call(lua_State* L)
{ {
luaL_checktype(L, 1, LUA_TTABLE); luaL_checktype(L, 1, LUA_TTABLE);
luaL_checktype(L, 2, LUA_TTABLE); luaL_checktype(L, 2, LUA_TTABLE);
luaL_checktype(L, 3, LUA_TTABLE); luaL_checktype(L, 3, LUA_TTABLE);
int us = luaL_checkinteger(L, 4); int us = luaL_checkinteger(L, 4);
FD_SET readset, writeset, errorset; fd_set readset, writeset, errorset;
FD_ZERO(&readset); FD_ZERO(&readset);
lua_pushnil(L); luatable_to_fdset(L, 1, readset);
while (lua_next(L, 1))
{
lua_pop(L, 1);
auto s = lua_checkblock<TCPSocket>(L, -1, "LuaEngineTCPSocket");
if (s->fd > 0)
{
FD_SET(s->fd, &readset);
}
}
FD_ZERO(&writeset); FD_ZERO(&writeset);
lua_pushnil(L); luatable_to_fdset(L, 2, writeset);
while (lua_next(L, 2))
{
lua_pop(L, 1);
auto s = lua_checkblock<TCPSocket>(L, -1, "LuaEngineTCPSocket");
if (s->fd > 0)
{
FD_SET(s->fd, &writeset);
}
}
FD_ZERO(&errorset); FD_ZERO(&errorset);
lua_pushnil(L); luatable_to_fdset(L, 3, errorset);
while (lua_next(L, 3))
{
lua_pop(L, 1);
auto s = lua_checkblock<TCPSocket>(L, -1, "LuaEngineTCPSocket");
if (s->fd > 0)
{
FD_SET(s->fd, &errorset);
}
}
timeval tm; timeval tm;
tm.tv_sec = us / 1000000; tm.tv_sec = us / 1000000;
tm.tv_usec = us % 1000000; tm.tv_usec = us % 1000000;
printf("[DEBUG] select() start\n");
int ret = select(1024, &readset, &writeset, &errorset, &tm); int ret = select(1024, &readset, &writeset, &errorset, &tm);
printf("[DEBUG] select() done. ret=%d\n", ret);
if (ret < 0) if (ret < 0)
{ {
@ -72,47 +74,9 @@ int select_call(lua_State* L)
} }
else else
{ {
lua_newtable(L); // ... RetT fdset_to_luatable(L, 1, readset); // +1
lua_pushnil(L); // ... RetT nil fdset_to_luatable(L, 2, writeset); // +1
while (lua_next(L, 1)) fdset_to_luatable(L, 3, errorset); // +1
{
lua_pop(L, 1); // ... RetT Socket
auto s = lua_checkblock<TCPSocket>(L, -1, "LuaEngineTCPSocket");
if (s->fd > 0 && FD_ISSET(s->fd, &readset))
{
lua_pushvalue(L, -1); // ... RetT Socket Socket
lua_pushboolean(L, true); // ... RetT Socket Socket true
lua_settable(L, -4); // ... RetT Socket
}
}
lua_newtable(L); // ... RetT
lua_pushnil(L); // ... RetT nil
while (lua_next(L, 2))
{
lua_pop(L, 1); // ... RetT Socket
auto s = lua_checkblock<TCPSocket>(L, -1, "LuaEngineTCPSocket");
if (s->fd > 0 && FD_ISSET(s->fd, &writeset))
{
lua_pushvalue(L, -1); // ... RetT Socket Socket
lua_pushboolean(L, true); // ... RetT Socket Socket true
lua_settable(L, -4); // ... RetT Socket
}
}
lua_newtable(L); // ... RetT
lua_pushnil(L); // ... RetT nil
while (lua_next(L, 3))
{
lua_pop(L, 1); // ... RetT Socket
auto s = lua_checkblock<TCPSocket>(L, -1, "LuaEngineTCPSocket");
if (s->fd > 0 && FD_ISSET(s->fd, &errorset))
{
lua_pushvalue(L, -1); // ... RetT Socket Socket
lua_pushboolean(L, true); // ... RetT Socket Socket true
lua_settable(L, -4); // ... RetT Socket
}
}
return 3; // ... RetT RetT RetT return 3; // ... RetT RetT RetT
} }

11
Socket.h Normal file
View File

@ -0,0 +1,11 @@
#include "include.h"
#include <vector>
class SocketData
{
public:
int fd;
bool nonblocking;
std::vector<char> data;
int buffsz;
};

14
TCP.h
View File

@ -1,5 +1,4 @@
#include "include.h" #include "Socket.h"
#include <vector>
/* /*
class TCPSocket class TCPSocket
@ -8,7 +7,7 @@ class TCPSocket
setblocking(nonblocking: boolean) setblocking(nonblocking: boolean)
listen([ip: string], port: int, [backlog: int]) Address default to 0.0.0.0, backlog default to 10. listen([ip: string], port: int, [backlog: int]) Address default to 0.0.0.0, backlog default to 10.
# Blocking mode: All non-expected error will be raised as exception. # Blocking mode: All unexpected error will be raised as exception.
connect(ip: string, port: int) connect(ip: string, port: int)
accept(): TCPSocket PeerIP PeerPort accept(): TCPSocket PeerIP PeerPort
send(data: string) All data will be sent before return. send(data: string) All data will be sent before return.
@ -20,12 +19,3 @@ class TCPSocket
send(data: string) send(data: string)
recv([maxsize: int]): string recv([maxsize: int]): string
*/ */
class TCPSocket
{
public:
int fd;
bool nonblocking;
std::vector<char> data;
int buffsz;
};

View File

@ -9,19 +9,19 @@ using namespace std;
int tcp_socket_dtor(lua_State* L) int tcp_socket_dtor(lua_State* L)
{ {
auto s = lua_checkblock<TCPSocket>(L, 1, "LuaEngineTCPSocket"); auto s = lua_checkblock<SocketData>(L, 1, "LuaEngineTCPSocket");
if (s->fd > 0) if (s->fd > 0)
{ {
closesocket(s->fd); closesocket(s->fd);
s->fd = -1; s->fd = -1;
} }
s->~TCPSocket(); s->~SocketData();
return 0; return 0;
} }
int tcp_socket_close(lua_State* L) int tcp_socket_close(lua_State* L)
{ {
auto s = lua_checkblock<TCPSocket>(L, 1, "LuaEngineTCPSocket"); auto s = lua_checkblock<SocketData>(L, 1, "LuaEngineTCPSocket");
if (s->fd > 0) if (s->fd > 0)
{ {
closesocket(s->fd); closesocket(s->fd);
@ -32,7 +32,7 @@ int tcp_socket_close(lua_State* L)
int tcp_socket_send(lua_State* L) int tcp_socket_send(lua_State* L)
{ {
auto s = lua_checkblock<TCPSocket>(L, 1, "LuaEngineTCPSocket"); auto s = lua_checkblock<SocketData>(L, 1, "LuaEngineTCPSocket");
size_t sz; size_t sz;
const char* str = luaL_checklstring(L, 2, &sz); const char* str = luaL_checklstring(L, 2, &sz);
size_t done = 0; size_t done = 0;
@ -59,7 +59,7 @@ int tcp_socket_send(lua_State* L)
int tcp_socket_recv(lua_State* L) int tcp_socket_recv(lua_State* L)
{ {
auto s = lua_checkblock<TCPSocket>(L, 1, "LuaEngineTCPSocket"); auto s = lua_checkblock<SocketData>(L, 1, "LuaEngineTCPSocket");
int ret = recv(s->fd, s->data.data(), s->buffsz, 0); int ret = recv(s->fd, s->data.data(), s->buffsz, 0);
if (ret < 0) if (ret < 0)
{ {
@ -79,14 +79,19 @@ int tcp_socket_recv(lua_State* L)
int tcp_socket_connect(lua_State* L) int tcp_socket_connect(lua_State* L)
{ {
auto s = lua_checkblock<TCPSocket>(L, 1, "LuaEngineTCPSocket"); auto s = lua_checkblock<SocketData>(L, 1, "LuaEngineTCPSocket");
const char* ip = luaL_checkstring(L, 2); const char* ip = luaL_checkstring(L, 2);
int port = luaL_checkinteger(L, 3); int port = luaL_checkinteger(L, 3);
sockaddr_in addr; sockaddr_in addr;
memset(&addr, 0, sizeof(addr)); memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET; addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(ip); if (inet_pton(AF_INET, ip, &addr.sin_addr) < 0)
{
int errcode = WSAGetLastError();
put_winerror(L, errcode, "inet_pton");
return lua_error(L);
}
addr.sin_port = htons(port); addr.sin_port = htons(port);
int ret = connect(s->fd, (const sockaddr*)&addr, sizeof(addr)); int ret = connect(s->fd, (const sockaddr*)&addr, sizeof(addr));
@ -107,7 +112,7 @@ int tcp_socket_connect(lua_State* L)
int tcp_socket_listen(lua_State* L) int tcp_socket_listen(lua_State* L)
{ {
auto s = lua_checkblock<TCPSocket>(L, 1, "LuaEngineTCPSocket"); auto s = lua_checkblock<SocketData>(L, 1, "LuaEngineTCPSocket");
const char* ip = NULL; const char* ip = NULL;
int port; int port;
int backlog = 10; int backlog = 10;
@ -134,7 +139,12 @@ int tcp_socket_listen(lua_State* L)
addr.sin_family = AF_INET; addr.sin_family = AF_INET;
if (ip && strcmp(ip, "0.0.0.0")) if (ip && strcmp(ip, "0.0.0.0"))
{ {
addr.sin_addr.s_addr = inet_addr(ip); if (inet_pton(AF_INET, ip, &addr.sin_addr) < 0)
{
int errcode = WSAGetLastError();
put_winerror(L, errcode, "inet_pton");
return lua_error(L);
}
} }
else else
{ {
@ -163,7 +173,7 @@ int tcp_socket_listen(lua_State* L)
int tcp_socket_setblocking(lua_State* L) int tcp_socket_setblocking(lua_State* L)
{ {
auto s = lua_checkblock<TCPSocket>(L, 1, "LuaEngineTCPSocket"); auto s = lua_checkblock<SocketData>(L, 1, "LuaEngineTCPSocket");
luaL_checkany(L, 2); luaL_checkany(L, 2);
bool blocking = lua_toboolean(L, 2); bool blocking = lua_toboolean(L, 2);
if (blocking != s->nonblocking) if (blocking != s->nonblocking)
@ -199,7 +209,7 @@ int tcp_socket_accept(lua_State* L);
void put_tcp_socket(lua_State* L, int fd, bool nonblocking) void put_tcp_socket(lua_State* L, int fd, bool nonblocking)
{ {
auto s = new (lua_newblock<TCPSocket>(L)) TCPSocket; auto s = new (lua_newblock<SocketData>(L)) SocketData;
if (luaL_newmetatable(L, "LuaEngineTCPSocket")) if (luaL_newmetatable(L, "LuaEngineTCPSocket"))
{ {
lua_setfield_function(L, "__gc", tcp_socket_dtor); lua_setfield_function(L, "__gc", tcp_socket_dtor);
@ -222,7 +232,7 @@ void put_tcp_socket(lua_State* L, int fd, bool nonblocking)
int tcp_socket_accept(lua_State* L) int tcp_socket_accept(lua_State* L)
{ {
auto s = lua_checkblock<TCPSocket>(L, 1, "LuaEngineTCPSocket"); auto s = lua_checkblock<SocketData>(L, 1, "LuaEngineTCPSocket");
sockaddr_in addr; sockaddr_in addr;
int addrsz = sizeof(addr); int addrsz = sizeof(addr);
int ret = accept(s->fd, (sockaddr*)&addr, &addrsz); int ret = accept(s->fd, (sockaddr*)&addr, &addrsz);
@ -237,7 +247,15 @@ int tcp_socket_accept(lua_State* L)
return lua_error(L); return lua_error(L);
} }
put_tcp_socket(L, ret, false); put_tcp_socket(L, ret, false);
lua_pushstring(L, inet_ntoa(addr.sin_addr));
char buffer[1024] = { 0 };
if (inet_ntop(AF_INET, &addr.sin_addr, buffer, 1024) < 0)
{
int errcode = WSAGetLastError();
put_winerror(L, errcode, "inet_ntop");
return lua_error(L);
}
lua_pushstring(L, buffer);
lua_pushinteger(L, ntohs(addr.sin_port)); lua_pushinteger(L, ntohs(addr.sin_port));
return 3; return 3;
} }

View File

16
UDP.h Normal file
View File

@ -0,0 +1,16 @@
#include "Socket.h"
/*
class UDPSocket
constructor()
close()
setblocking(nonblocking: boolean)
setbroadcast(isbroadcast: boolean) Broadcast default to false.
listen([ip: string], port: int) Address default to 0.0.0.0.
connect(ip: string, port: int)
send(data: string)
recv([maxsize: int]): string. Default to 4KB.
sendto([ip: string], port: int, data: string) If ip is empty, default to 255.255.255.255 (broadcast)
recvfrom(): data: string, ip: string, port: int
*/

348
UDPWin.cpp Normal file
View File

@ -0,0 +1,348 @@
#include "UDP.h"
#ifdef _WIN32
#define _WIN32_WINNT 0x0A00 // Win10
#include <winsock2.h>
#include <ws2tcpip.h>
int udp_socket_dtor(lua_State* L)
{
auto s = lua_checkblock<SocketData>(L, 1, "LuaEngineUDPSocket");
if (s->fd > 0)
{
closesocket(s->fd);
s->fd = -1;
}
s->~SocketData();
return 0;
}
int udp_socket_close(lua_State* L)
{
auto s = lua_checkblock<SocketData>(L, 1, "LuaEngineUDPSocket");
if (s->fd > 0)
{
closesocket(s->fd);
s->fd = -1;
}
return 0;
}
int udp_socket_send(lua_State* L)
{
auto s = lua_checkblock<SocketData>(L, 1, "LuaEngineUDPSocket");
size_t sz;
const char* str = luaL_checklstring(L, 2, &sz);
int ret = send(s->fd, str, sz, 0);
if (ret < 0)
{
int errcode = WSAGetLastError();
if (s->nonblocking && errcode == WSAEWOULDBLOCK)
{
lua_pushboolean(L, true);
return 1;
}
put_winerror(L, errcode, "send");
return lua_error(L);
}
return 0;
}
int udp_socket_recv(lua_State* L)
{
auto s = lua_checkblock<SocketData>(L, 1, "LuaEngineUDPSocket");
int ret = recv(s->fd, s->data.data(), s->buffsz, 0);
if (ret < 0)
{
int errcode = WSAGetLastError();
if (s->nonblocking && errcode == WSAEWOULDBLOCK)
{
return 0;
}
put_winerror(L, errcode, "recv");
return lua_error(L);
}
lua_pushlstring(L, s->data.data(), ret);
return 1;
}
int udp_socket_sendto(lua_State* L)
{
auto s = lua_checkblock<SocketData>(L, 1, "LuaEngineUDPSocket");
const char* ip = NULL;
int port;
size_t sz;
const char* str = NULL;
if (lua_type(L, 2) == LUA_TSTRING)
{
ip = luaL_checkstring(L, 2);
port = luaL_checkinteger(L, 3);
str = luaL_checklstring(L, 4, &sz);
}
else
{
port = luaL_checkinteger(L, 2);
str = luaL_checklstring(L, 3, &sz);
}
sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
if (ip && strcmp(ip, "255.255.255.255"))
{
if (inet_pton(AF_INET, ip, &addr.sin_addr) < 0)
{
int errcode = WSAGetLastError();
put_winerror(L, errcode, "inet_pton");
return lua_error(L);
}
}
else
{
addr.sin_addr.s_addr = INADDR_BROADCAST;
}
int ret = sendto(s->fd, str, sz, 0, (const sockaddr*)&addr, sizeof(addr));
if (ret < 0)
{
int errcode = WSAGetLastError();
if (s->nonblocking && errcode == WSAEWOULDBLOCK)
{
lua_pushboolean(L, true);
return 1;
}
put_winerror(L, errcode, "sendto");
return lua_error(L);
}
return 0;
}
int udp_socket_recvfrom(lua_State* L)
{
auto s = lua_checkblock<SocketData>(L, 1, "LuaEngineUDPSocket");
sockaddr_in addr;
int addrlen = sizeof(addr);
int ret = recvfrom(s->fd, s->data.data(), s->buffsz, 0, (sockaddr*)&addr, &addrlen);
if (ret < 0)
{
int errcode = WSAGetLastError();
if (s->nonblocking && errcode == WSAEWOULDBLOCK)
{
return 0;
}
put_winerror(L, errcode, "recvfrom");
return lua_error(L);
}
char buffer[1024] = { 0 };
if (inet_ntop(AF_INET, &addr.sin_addr, buffer, 1024) < 0)
{
int errcode = WSAGetLastError();
put_winerror(L, errcode, "inet_ntop");
return lua_error(L);
}
lua_pushlstring(L, s->data.data(), ret);
lua_pushstring(L, buffer);
lua_pushinteger(L, ntohs(addr.sin_port));
return 3;
}
int udp_socket_connect(lua_State* L)
{
auto s = lua_checkblock<SocketData>(L, 1, "LuaEngineUDPSocket");
const char* ip = luaL_checkstring(L, 2);
int port = luaL_checkinteger(L, 3);
sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
if (inet_pton(AF_INET, ip, &addr.sin_addr) < 0)
{
int errcode = WSAGetLastError();
put_winerror(L, errcode, "inet_pton");
return lua_error(L);
}
addr.sin_port = htons(port);
int ret = connect(s->fd, (const sockaddr*)&addr, sizeof(addr));
if (ret < 0)
{
int errcode = WSAGetLastError();
if (s->nonblocking && errcode == WSAEWOULDBLOCK)
{
lua_pushboolean(L, true);
return 1;
}
put_winerror(L, errcode, "connect");
return lua_error(L);
}
return 0;
}
int udp_socket_setblocking(lua_State* L)
{
auto s = lua_checkblock<SocketData>(L, 1, "LuaEngineUDPSocket");
luaL_checkany(L, 2);
bool blocking = lua_toboolean(L, 2);
if (blocking != s->nonblocking)
{
return 0;
}
if (blocking) // set to blocking
{
u_long arg = 0;
int ret = ioctlsocket(s->fd, FIONBIO, &arg);
if (ret)
{
int errcode = WSAGetLastError();
put_winerror(L, errcode, "ioctlsocket");
return lua_error(L);
}
}
else // set to nonblocking
{
u_long arg = 1;
int ret = ioctlsocket(s->fd, FIONBIO, &arg);
if (ret)
{
int errcode = WSAGetLastError();
put_winerror(L, errcode, "ioctlsocket");
return lua_error(L);
}
}
return 0;
}
int udp_socket_setbroadcast(lua_State* L)
{
auto s = lua_checkblock<SocketData>(L, 1, "LuaEngineUDPSocket");
socklen_t opt = 0;
if (!lua_isnone(L, 2) && lua_toboolean(L, 2))
{
opt = 1;
}
int ret = setsockopt(s->fd, SOL_SOCKET, SO_BROADCAST, (const char*)&opt, sizeof(opt));
if (ret < 0)
{
int errcode = WSAGetLastError();
put_winerror(L, errcode, "setsockopt");
return lua_error(L);
}
return 0;
}
int udp_socket_listen(lua_State* L)
{
auto s = lua_checkblock<SocketData>(L, 1, "LuaEngineUDPSocket");
const char* ip = NULL;
int port;
if (lua_type(L, 2) == LUA_TSTRING)
{
ip = luaL_checkstring(L, 2);
port = luaL_checkinteger(L, 3);
}
else
{
port = luaL_checkinteger(L, 2);
}
sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
if (ip && strcmp(ip, "0.0.0.0"))
{
if (inet_pton(AF_INET, ip, &addr.sin_addr) < 0)
{
int errcode = WSAGetLastError();
put_winerror(L, errcode, "inet_pton");
return lua_error(L);
}
}
else
{
addr.sin_addr.s_addr = INADDR_ANY;
}
addr.sin_port = htons(port);
int ret = bind(s->fd, (const sockaddr*)&addr, sizeof(addr));
if (ret < 0)
{
int errcode = WSAGetLastError();
put_winerror(L, errcode, "bind");
return lua_error(L);
}
return 0;
}
void put_udp_socket(lua_State* L, int fd, bool nonblocking)
{
auto s = new (lua_newblock<SocketData>(L)) SocketData;
if (luaL_newmetatable(L, "LuaEngineUDPSocket"))
{
lua_setfield_function(L, "__gc", udp_socket_dtor);
lua_newtable(L);
lua_setfield_function(L, "close", udp_socket_close);
lua_setfield_function(L, "send", udp_socket_send);
lua_setfield_function(L, "recv", udp_socket_recv);
lua_setfield_function(L, "sendto", udp_socket_sendto);
lua_setfield_function(L, "recvfrom", udp_socket_recvfrom);
lua_setfield_function(L, "listen", udp_socket_listen);
lua_setfield_function(L, "connect", udp_socket_connect);
lua_setfield_function(L, "setblocking", udp_socket_setblocking);
lua_setfield_function(L, "setbroadcast", udp_socket_setbroadcast);
lua_setfield(L, -2, "__index");
}
lua_setmetatable(L, -2);
s->fd = fd;
s->nonblocking = nonblocking;
s->buffsz = 4096;
s->data.resize(s->buffsz);
}
int udp_socket_new(lua_State* L)
{
bool nonblocking = false;
if (!lua_isnone(L, 1))
{
if (lua_toboolean(L, 1))
{
nonblocking = true;
}
}
int fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0)
{
int errcode = WSAGetLastError();
put_winerror(L, errcode, "socket");
return lua_error(L);
}
if (nonblocking)
{
u_long arg = 1;
int ret = ioctlsocket(fd, FIONBIO, &arg);
if (ret)
{
int errcode = WSAGetLastError();
closesocket(fd);
put_winerror(L, errcode, "ioctlsocket");
return lua_error(L);
}
}
put_udp_socket(L, fd, nonblocking);
return 1;
}
void InitUDPSocket(lua_State* L)
{
lua_getglobal(L, "package");
lua_getfield(L, -1, "loaded");
lua_pushcfunction(L, udp_socket_new);
lua_setfield(L, -2, "UDPSocket");
lua_pop(L, 2);
}
#endif // end of _WIN32

View File

@ -33,6 +33,12 @@ T* lua_checkblock(lua_State* L, int idx, const char* name)
return (T*)luaL_checkudata(L, idx, name); return (T*)luaL_checkudata(L, idx, name);
} }
template<typename T>
T* lua_testblock(lua_State* L, int idx, const char* name)
{
return (T*)luaL_testudata(L, idx, name);
}
// Shared Functions // Shared Functions
void put_surface(lua_State* L, SDL_Surface* surf); void put_surface(lua_State* L, SDL_Surface* surf);
void put_texture(lua_State* L, SDL_Texture* text); void put_texture(lua_State* L, SDL_Texture* text);
@ -45,6 +51,8 @@ void InitMusic(lua_State* L);
void InitEvent(lua_State* L); void InitEvent(lua_State* L);
void InitCommon(lua_State* L); void InitCommon(lua_State* L);
void InitTCPSocket(lua_State* L); void InitTCPSocket(lua_State* L);
void InitUDPSocket(lua_State* L);
void InitNetwork(lua_State* L);
void InitThread(lua_State* L); void InitThread(lua_State* L);
void InitSocketSelector(lua_State* L); void InitSocketSelector(lua_State* L);

View File

@ -1,6 +1,7 @@
#include "LuaEngine.h" #include "LuaEngine.h"
#include <string> #include <string>
#include <iostream> #include <iostream>
#include <direct.h>
using namespace std; using namespace std;
string LoadFile(const string& filename) string LoadFile(const string& filename)
@ -28,7 +29,8 @@ int main()
lua_State* L = luaL_newstate(); lua_State* L = luaL_newstate();
luaL_openlibs(L); luaL_openlibs(L);
InitLuaEngine(L); InitLuaEngine(L);
string code = LoadFile("game/app.lua"); _chdir("game");
string code = LoadFile("test.lua");
if (luaL_loadstring(L, code.c_str())) if (luaL_loadstring(L, code.c_str()))
{ {
cout << lua_tostring(L, -1) << endl; cout << lua_tostring(L, -1) << endl;