diff --git a/CMakeLists.txt b/CMakeLists.txt index 4b8cd033..f6331478 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -44,11 +44,6 @@ if(PK_ENABLE_OS) add_definitions(-DPK_ENABLE_OS=1) endif() -option(PK_MODULE_WIN32 "" OFF) -if(PK_MODULE_WIN32) - add_definitions(-DPK_MODULE_WIN32=1) -endif() - # PK_IS_MAIN determines whether the project is being used from root # or if it is added as a dependency (through add_subdirectory for example). if ("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_SOURCE_DIR}") @@ -87,7 +82,3 @@ if(UNIX) target_link_libraries(${PROJECT_NAME} dl) endif() endif() - -if(PK_MODULE_WIN32) - target_link_libraries(${PROJECT_NAME} winmm.lib) -endif() diff --git a/include/pocketpy/interpreter/modules.h b/include/pocketpy/interpreter/modules.h index 0aee221b..c9657468 100644 --- a/include/pocketpy/interpreter/modules.h +++ b/include/pocketpy/interpreter/modules.h @@ -14,4 +14,4 @@ void pk__add_module_enum(); void pk__add_module_linalg(); void pk__add_module_array2d(); -void pk__add_module_win32(); \ No newline at end of file +void pk__add_module_conio(); \ No newline at end of file diff --git a/include/typings/conio.pyi b/include/typings/conio.pyi new file mode 100644 index 00000000..c9c7b873 --- /dev/null +++ b/include/typings/conio.pyi @@ -0,0 +1,2 @@ +def _kbhit() -> int: ... +def _getch() -> int: ... diff --git a/include/typings/line_profiler.pyi b/include/typings/line_profiler.pyi deleted file mode 100644 index c35066f7..00000000 --- a/include/typings/line_profiler.pyi +++ /dev/null @@ -1,10 +0,0 @@ -from typing import Callable - -class LineProfiler: - def __init__(self): ... - - def add_function(self, func: Callable) -> None: ... - - def runcall(self, func: Callable, *args) -> None: ... - - def print_stats(self) -> None: ... diff --git a/include/typings/win32.pyi b/include/typings/win32.pyi deleted file mode 100644 index d9dc5a16..00000000 --- a/include/typings/win32.pyi +++ /dev/null @@ -1,4 +0,0 @@ -def _kbhit() -> int: ... -def _getch() -> int: ... - -def PlaySoundA(pszSound: str, hmod: int, fdwSound: int) -> bool: ... diff --git a/src/interpreter/vm.c b/src/interpreter/vm.c index 26442a5b..e1708aae 100644 --- a/src/interpreter/vm.c +++ b/src/interpreter/vm.c @@ -216,8 +216,7 @@ void VM__ctor(VM* self) { pk__add_module_traceback(); pk__add_module_enum(); - // add win32 module - pk__add_module_win32(); + pk__add_module_conio(); // add python builtins do { diff --git a/src/modules/conio.c b/src/modules/conio.c new file mode 100644 index 00000000..0bc43fcb --- /dev/null +++ b/src/modules/conio.c @@ -0,0 +1,128 @@ +#include "pocketpy/pocketpy.h" +#include + +#if PY_SYS_PLATFORM == 0 + +#include +#include + +#elif PY_SYS_PLATFORM == 3 || PY_SYS_PLATFORM == 5 + +#include +#include +#include +#include +#include + +// 保存原始终端设置 +static struct termios orig_termios; +static bool orig_termios_set; + +// 还原终端设置 +static void reset_terminal_mode() { tcsetattr(0, TCSANOW, &orig_termios); } + +// 设置终端为非阻塞模式 +static void set_conio_terminal_mode_if_needed() { + if(orig_termios_set) return; + struct termios new_termios; + + // 获取当前终端设置 + tcgetattr(0, &orig_termios); + memcpy(&new_termios, &orig_termios, sizeof(new_termios)); + + // 禁用缓冲和回显 + new_termios.c_lflag &= ~(ICANON | ECHO); + tcsetattr(0, TCSANOW, &new_termios); + + atexit(reset_terminal_mode); + orig_termios_set = true; +} + +// 检查是否有按键按下 +int _kbhit() { + set_conio_terminal_mode_if_needed(); + + struct termios term; + int oldf; + int ch; + int old_flags; + + // 获取终端设置 + tcgetattr(0, &term); + oldf = term.c_lflag; + term.c_lflag &= ~(ICANON | ECHO); + tcsetattr(0, TCSANOW, &term); + + // 设置文件描述符为非阻塞 + old_flags = fcntl(STDIN_FILENO, F_GETFL, 0); + fcntl(STDIN_FILENO, F_SETFL, old_flags | O_NONBLOCK); + + // 检查是否有输入 + ch = getchar(); + + // 还原文件描述符设置 + fcntl(STDIN_FILENO, F_SETFL, old_flags); + + // 还原终端设置 + term.c_lflag = oldf; + tcsetattr(0, TCSANOW, &term); + + if(ch != EOF) { + ungetc(ch, stdin); + return 1; + } + + return 0; +} + +// 获取一个字符 +int _getch() { + set_conio_terminal_mode_if_needed(); + + int ch; + struct termios oldt, newt; + + // 获取当前终端设置 + tcgetattr(STDIN_FILENO, &oldt); + newt = oldt; + + // 禁用缓冲和回显 + newt.c_lflag &= ~(ICANON | ECHO); + tcsetattr(STDIN_FILENO, TCSANOW, &newt); + + // 读取字符 + ch = getchar(); + + // 还原终端设置 + tcsetattr(STDIN_FILENO, TCSANOW, &oldt); + + return ch; +} +#endif + +#if PK_IS_DESKTOP_PLATFORM && PK_ENABLE_OS +static bool conio_kbhit(int argc, py_Ref argv) { + PY_CHECK_ARGC(0); + int ret = _kbhit(); + py_newint(py_retval(), ret); + return true; +} + +static bool conio_getch(int argc, py_Ref argv) { + PY_CHECK_ARGC(0); + int ret = _getch(); + py_newint(py_retval(), ret); + return true; +} + +void pk__add_module_conio() { + py_Ref mod = py_newmodule("conio"); + py_bindfunc(mod, "_kbhit", conio_kbhit); + py_bindfunc(mod, "_getch", conio_getch); +} + +#else + +void pk__add_module_conio() {} + +#endif diff --git a/src/modules/win32.c b/src/modules/win32.c deleted file mode 100644 index 42156b66..00000000 --- a/src/modules/win32.c +++ /dev/null @@ -1,47 +0,0 @@ -#include "pocketpy/pocketpy.h" - -#if defined(_WIN32) && defined(PK_MODULE_WIN32) - -#include -#include - -static bool win32__kbhit(int argc, py_Ref argv) { - PY_CHECK_ARGC(0); - int ret = _kbhit(); - py_newint(py_retval(), ret); - return true; -} - -static bool win32__getch(int argc, py_Ref argv) { - PY_CHECK_ARGC(0); - int ret = _getch(); - py_newint(py_retval(), ret); - return true; -} - -static bool win32_PlaySoundA(int argc, py_Ref argv) { - PY_CHECK_ARGC(3); - PY_CHECK_ARG_TYPE(0, tp_str); - PY_CHECK_ARG_TYPE(1, tp_int); - PY_CHECK_ARG_TYPE(2, tp_int); - const char* pszSound = py_tostr(argv); - py_i64 hmod = py_toint(py_arg(1)); - py_i64 fdwSound = py_toint(py_arg(2)); - int ret = PlaySoundA(pszSound, (HMODULE)hmod, fdwSound); - py_newbool(py_retval(), ret); - return true; -} - -#endif - - -void pk__add_module_win32() { -#if defined(_WIN32) && defined(PK_MODULE_WIN32) - py_Ref mod = py_newmodule("win32"); - - py_bindfunc(mod, "_kbhit", win32__kbhit); - py_bindfunc(mod, "_getch", win32__getch); - - py_bindfunc(mod, "PlaySoundA", win32_PlaySoundA); -#endif -}