pkpy 是一个轻量级(~15K LOC)Python 3.x 游戏脚本解释器,用 C11 编写。
它旨在成为lua游戏脚本的替代品,具有优雅的语法、强大的功能和有竞争力的性能。 pkpy 非常容易通过单个头文件pocketpy.h
嵌入,无需外部依赖。
请参阅 https://pocketpy.dev 了解详细信息并尝试以下资源。
pkpy 应该可以在任何具有 C11 编译器的平台上运行。这些平台都经过官方测试。
您有两种选择将 pkpy 集成到您的项目中。
在我们的 GitHub 发布页面下载pocketpy.h
和pocketpy.c
。并将其#include
到您的项目中。
将整个存储库作为子模块克隆到您的项目中,在 CMakelists.txt 中添加以下行:
add_subdirectory (pocketpy)
target_link_libraries ( pocketpy)
有关详细信息,请参阅 CMakeLists.txt。
如果 CI 徽章为绿色,则在生产中使用main
分支是安全的。
要在您的项目中编译它,必须设置这些标志:
--std=c11
标志/utf-8
标志NDEBUG
宏应该为发布版本定义,否则性能会很差对于合并构建,运行python amalgamate.py
在amalgamated/
目录中生成pocketpy.c
和pocketpy.h
。
#include "pocketpy.h"
#include
static bool int_add ( int argc , py_Ref argv ) {
PY_CHECK_ARGC ( 2 );
PY_CHECK_ARG_TYPE ( 0 , tp_int );
PY_CHECK_ARG_TYPE ( 1 , tp_int );
py_i64 a = py_toint ( py_arg ( 0 ));
py_i64 b = py_toint ( py_arg ( 1 ));
py_newint ( py_retval (), a + b );
return true;
}
int main () {
// Initialize pocketpy
py_initialize ();
// Hello world!
bool ok = py_exec ( "print('Hello world!')" , "" , EXEC_MODE , NULL );
if (! ok ) goto __ERROR;
// Create a list: [1, 2, 3]
py_Ref r0 = py_getreg ( 0 );
py_newlistn ( r0 , 3 );
py_newint ( py_list_getitem ( r0 , 0 ), 1 );
py_newint ( py_list_getitem ( r0 , 1 ), 2 );
py_newint ( py_list_getitem ( r0 , 2 ), 3 );
// Eval the sum of the list
py_Ref f_sum = py_getbuiltin ( py_name ( "sum" ));
py_push ( f_sum );
py_pushnil ();
py_push ( r0 );
ok = py_vectorcall ( 1 , 0 );
if (! ok ) goto __ERROR;
printf ( "Sum of the list: %dn" , ( int ) py_toint ( py_retval ())); // 6
// Bind native `int_add` as a global variable
py_newnativefunc ( r0 , int_add );
py_setglobal ( py_name ( "add" ), r0 );
// Call `add` in python
ok = py_exec ( "add(3, 7)" , "" , EVAL_MODE , NULL );
if (! ok ) goto __ERROR;
py_i64 res = py_toint ( py_retval ());
printf ( "Sum of 2 variables: %dn" , ( int ) res ); // 10
py_finalize ();
return 0 ;
__ERROR:
py_printexc ();
py_finalize ();
return 1 ;
}
姓名 | 例子 | 支持 |
---|---|---|
如果否则 | if..else..elif | ✅ |
环形 | for/while/break/continue | ✅ |
功能 | def f(x,*args,y=1): | ✅ |
子类 | class A(B): | ✅ |
列表 | [1, 2, 'a'] | ✅ |
列表比较 | [i for i in range(5)] | ✅ |
片 | a[1:2], a[:2], a[1:] | ✅ |
元组 | (1, 2, 'a') | ✅ |
词典 | {'a': 1, 'b': 2} | ✅ |
F 弦 | f'value is {x}' | ✅ |
开箱 | a, b = 1, 2 | ✅ |
明星拆箱 | a, *b = [1, 2, 3] | ✅ |
例外 | raise/try..catch..finally | ✅ |
动态代码 | eval()/exec() | ✅ |
反射 | hasattr()/getattr()/setattr() | ✅ |
进口 | import/from..import | ✅ |
上下文块 | with | ✅ |
类型注释 | def f(a:int, b:float=1) | ✅ |
发电机 | yield i | ✅ |
装饰者 | @cache | ✅ |
目前,pkpy 与 cpython 3.9 一样快。 cpython 3.9 的性能结果适用于 pkpy。
有关详细信息,请参阅 https://pocketpy.dev/performance/。
这是在 Intel i5-12400F、WSL(Ubuntu 20.04 LTS)上进行 primes 基准测试的结果,大致反映了 c++、lua、pkpy 和 cpython 之间的性能。
姓名 | 版本 | 时间 | 文件 |
---|---|---|---|
由 小码哥发布于 | gnu++11 | 0.104s ■□□□□□□□□□□□□□□□ | 基准/primes.cpp |
卢阿 | 5.3.3 | 1.576s ■■■■■■■■■□□□□□□□ | 基准测试/primes.lua |
PKP | 1.2.7 | 2.385s ■■■■■■■■■■■■■□□□ | 基准/primes.py |
python | 3.8.10 | 2.871s ■■■■■■■■■■■■■■■■ | 基准/primes.py |
描述 | |
---|---|
TIC-80 | TIC-80 是一款用于制作、玩和分享小游戏的梦幻计算机。 |
pyjs | Max / MSP 的 Python3 外部。 |
新月 | Crescent 是一款跨平台 2D 格斗和格斗游戏引擎。 |
奥克斯比 | orx 引擎的 Python 扩展。 |
CANopen术语 | 适用于 CANopen CC 网络和设备的开源软件工具。 |
在此处提交拉取请求以添加您的项目。
欢迎各种贡献。
如果您发现 pkpy 有用,请考虑为该存储库加注星标 (●'◡'●)
您可以通过以下方式赞助该项目。
您的赞助将帮助我们不断发展pkpy。
python
Python 编程语言的官方实现。
字节跑
极好的学习材料。它说明了Python 虚拟机的工作原理。
麻省理工学院许可证