mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 19:40:18 +00:00
...
This commit is contained in:
parent
ed669b4069
commit
e979ab7107
@ -3,28 +3,123 @@
|
|||||||
#include "box2d/b2_world.h"
|
#include "box2d/b2_world.h"
|
||||||
#include "box2d/box2d.h"
|
#include "box2d/box2d.h"
|
||||||
#include "pocketpy/pocketpy.h"
|
#include "pocketpy/pocketpy.h"
|
||||||
#include <cstdlib>
|
|
||||||
|
|
||||||
namespace pkpy{
|
namespace pkpy{
|
||||||
|
template<>
|
||||||
template<>
|
inline b2Vec2 py_cast<b2Vec2>(VM* vm, PyObject* obj){
|
||||||
inline b2Vec2 py_cast<b2Vec2>(VM* vm, PyObject* obj){
|
|
||||||
Vec2 v = py_cast<Vec2>(vm, obj);
|
Vec2 v = py_cast<Vec2>(vm, obj);
|
||||||
return b2Vec2(v.x, v.y);
|
return b2Vec2(v.x, v.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
inline b2Vec2 _py_cast<b2Vec2>(VM* vm, PyObject* obj){
|
inline b2Vec2 _py_cast<b2Vec2>(VM* vm, PyObject* obj){
|
||||||
Vec2 v = _py_cast<Vec2>(vm, obj);
|
Vec2 v = _py_cast<Vec2>(vm, obj);
|
||||||
return b2Vec2(v.x, v.y);
|
return b2Vec2(v.x, v.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline PyObject* py_var(VM* vm, b2Vec2 v){
|
||||||
|
return py_var(vm, Vec2(v.x, v.y));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline PyObject* py_var(VM* vm, b2Vec2 v){
|
using namespace pkpy;
|
||||||
return py_var(vm, Vec2(v.x, v.y));
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace imbox2d{
|
namespace imbox2d{
|
||||||
|
|
||||||
|
// maybe we will use this class later
|
||||||
|
struct PyDebugDraw: b2Draw{
|
||||||
|
PK_ALWAYS_PASS_BY_POINTER(PyDebugDraw)
|
||||||
|
|
||||||
|
VM* vm;
|
||||||
|
PyObject* draw_like;
|
||||||
|
|
||||||
|
PyDebugDraw(VM* vm): vm(vm){}
|
||||||
|
|
||||||
|
void DrawPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color) override{
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawSolidPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color) override{
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawCircle(const b2Vec2& center, float radius, const b2Color& color) override{
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawSolidCircle(const b2Vec2& center, float radius, const b2Vec2& axis, const b2Color& color) override{
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawSegment(const b2Vec2& p1, const b2Vec2& p2, const b2Color& color) override{
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawTransform(const b2Transform& xf) override{
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawPoint(const b2Vec2& p, float size, const b2Color& color) override{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PyContactListener: b2ContactListener{
|
||||||
|
PK_ALWAYS_PASS_BY_POINTER(PyContactListener)
|
||||||
|
VM* vm;
|
||||||
|
PyContactListener(VM* vm): vm(vm){}
|
||||||
|
|
||||||
|
void _contact_f(b2Contact* contact, StrName name){
|
||||||
|
auto a = contact->GetFixtureA()->GetBody()->GetUserData().pointer;
|
||||||
|
auto b = contact->GetFixtureB()->GetBody()->GetUserData().pointer;
|
||||||
|
Body* bodyA = reinterpret_cast<Body*>(a);
|
||||||
|
Body* bodyB = reinterpret_cast<Body*>(b);
|
||||||
|
PyObject* self;
|
||||||
|
PyObject* f;
|
||||||
|
f = vm->get_unbound_method(bodyA->obj, name, &self, false);
|
||||||
|
if(f != nullptr) vm->call_method(self, f, VAR_T(PyBody, bodyB));
|
||||||
|
f = vm->get_unbound_method(bodyB->obj, name, &self, false);
|
||||||
|
if(f != nullptr) vm->call_method(self, f, VAR_T(PyBody, bodyA));
|
||||||
|
}
|
||||||
|
|
||||||
|
void BeginContact(b2Contact* contact) override {
|
||||||
|
DEF_SNAME(on_contact_begin);
|
||||||
|
_contact_f(contact, on_contact_begin);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EndContact(b2Contact* contact) override {
|
||||||
|
DEF_SNAME(on_contact_end);
|
||||||
|
_contact_f(contact, on_contact_end);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PyBody{
|
||||||
|
PY_CLASS(PyBody, box2d, Body)
|
||||||
|
PK_ALWAYS_PASS_BY_POINTER(PyBody)
|
||||||
|
|
||||||
|
b2Body* body;
|
||||||
|
b2Fixture* fixture;
|
||||||
|
PyObject* node_like;
|
||||||
|
|
||||||
|
PyBody() = default;
|
||||||
|
|
||||||
|
void _gc_mark() {
|
||||||
|
PK_OBJ_MARK(node_like);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _register(VM* vm, PyObject* mod, PyObject* type);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PyWorld {
|
||||||
|
PY_CLASS(PyWorld, box2d, World)
|
||||||
|
PK_ALWAYS_PASS_BY_POINTER(PyWorld)
|
||||||
|
|
||||||
|
b2World world;
|
||||||
|
PyContactListener _contact_listener;
|
||||||
|
PyDebugDraw _debug_draw;
|
||||||
|
|
||||||
|
PyWorld(VM* vm);
|
||||||
|
|
||||||
|
void _gc_mark(){
|
||||||
|
PK_OBJ_MARK(_debug_draw.draw_like);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _register(VM* vm, PyObject* mod, PyObject* type);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
struct Body final{
|
struct Body final{
|
||||||
b2Body* body;
|
b2Body* body;
|
||||||
@ -128,17 +223,18 @@ struct Body final{
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PyBody: OpaquePointer<Body>{
|
|
||||||
PY_CLASS(PyBody, box2d, Body)
|
|
||||||
|
|
||||||
using OpaquePointer<Body>::OpaquePointer;
|
|
||||||
static void _register(VM* vm, PyObject* mod, PyObject* type);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
inline PyObject* get_body_object(b2Body* p){
|
||||||
|
auto userdata = p->GetUserData().pointer;
|
||||||
|
return reinterpret_cast<PyObject*>(userdata);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace imbox2d
|
} // namespace imbox2d
|
||||||
|
|
||||||
void add_module_box2d(VM* vm);
|
namespace pkpy{
|
||||||
|
inline void add_module_box2d(VM* vm){
|
||||||
} // namespace pkpy
|
PyObject* mod = vm->new_module("box2d");
|
||||||
|
imbox2d::PyBody::register_class(vm, mod);
|
||||||
|
imbox2d::PyWorld::register_class(vm, mod);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
#include "box2d/b2_world.h"
|
||||||
|
#include "box2d/b2_world_callbacks.h"
|
||||||
|
#include "box2d_bindings.hpp"
|
||||||
|
|
||||||
|
using namespace pkpy;
|
||||||
|
|
||||||
|
namespace imbox2d{
|
||||||
|
|
||||||
|
|
||||||
|
void PyBody::_register(VM* vm, PyObject* mod, PyObject* type){
|
||||||
|
vm->bind(type, "__new__(cls, world: World, node: _NodeLike = None)",
|
||||||
|
[](VM* vm, ArgsView args){
|
||||||
|
PyWorld& world = CAST(PyWorld&, args[1]);
|
||||||
|
PyObject* node = args[2];
|
||||||
|
PyObject* obj = VAR_T(PyBody, PyBody());
|
||||||
|
PyBody& body = _CAST(PyBody&, obj);
|
||||||
|
b2BodyDef def;
|
||||||
|
def.type = b2_dynamicBody;
|
||||||
|
// a weak reference to this object
|
||||||
|
def.userData.pointer = reinterpret_cast<uintptr_t>(obj);
|
||||||
|
body.body = world.world.CreateBody(&def);
|
||||||
|
body.fixture = nullptr;
|
||||||
|
body.node_like = node;
|
||||||
|
return obj;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace imbox2d
|
@ -2,122 +2,47 @@
|
|||||||
#include "box2d/b2_world_callbacks.h"
|
#include "box2d/b2_world_callbacks.h"
|
||||||
#include "box2d_bindings.hpp"
|
#include "box2d_bindings.hpp"
|
||||||
|
|
||||||
namespace pkpy{
|
using namespace pkpy;
|
||||||
namespace imbox2d{
|
|
||||||
|
namespace imbox2d{
|
||||||
|
|
||||||
|
struct MyRayCastCallback: b2RayCastCallback{
|
||||||
|
PK_ALWAYS_PASS_BY_POINTER(MyRayCastCallback)
|
||||||
|
|
||||||
// This class captures the closest hit shape.
|
|
||||||
class MyRayCastCallback : public b2RayCastCallback
|
|
||||||
{
|
|
||||||
VM* vm;
|
VM* vm;
|
||||||
public:
|
|
||||||
List result;
|
List result;
|
||||||
MyRayCastCallback(VM* vm): vm(vm) {}
|
MyRayCastCallback(VM* vm): vm(vm) {}
|
||||||
|
|
||||||
float ReportFixture(b2Fixture* fixture, const b2Vec2& point,
|
float ReportFixture(b2Fixture* fixture, const b2Vec2& point, const b2Vec2& normal, float fraction){
|
||||||
const b2Vec2& normal, float fraction)
|
result.push_back(get_body_object(fixture->GetBody()));
|
||||||
{
|
|
||||||
auto userdata = fixture->GetBody()->GetUserData().pointer;
|
|
||||||
Body* body = reinterpret_cast<Body*>(userdata);
|
|
||||||
result.push_back(VAR_T(PyBody, body));
|
|
||||||
// if(only_one) return 0;
|
// if(only_one) return 0;
|
||||||
return fraction;
|
return fraction;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class MyBoxCastCallback: public b2QueryCallback{
|
struct MyBoxCastCallback: b2QueryCallback{
|
||||||
|
PK_ALWAYS_PASS_BY_POINTER(MyBoxCastCallback)
|
||||||
|
|
||||||
VM* vm;
|
VM* vm;
|
||||||
public:
|
|
||||||
List result;
|
List result;
|
||||||
MyBoxCastCallback(VM* vm): vm(vm) {}
|
MyBoxCastCallback(VM* vm): vm(vm) {}
|
||||||
|
|
||||||
bool ReportFixture(b2Fixture* fixture) override{
|
bool ReportFixture(b2Fixture* fixture) override{
|
||||||
auto userdata = fixture->GetBody()->GetUserData().pointer;
|
result.push_back(get_body_object(fixture->GetBody()));
|
||||||
Body* body = reinterpret_cast<Body*>(userdata);
|
|
||||||
result.push_back(VAR_T(PyBody, body));
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// maybe we will use this class later
|
/****************** PyWorld ******************/
|
||||||
class PyDebugDraw: public b2Draw{
|
PyWorld::PyWorld(VM* vm): world(b2Vec2(0, 0)), _contact_listener(vm), _debug_draw(vm){
|
||||||
VM* vm;
|
_debug_draw.draw_like = vm->None;
|
||||||
public:
|
world.SetAllowSleeping(true);
|
||||||
PyDebugDraw(VM* vm): vm(vm){}
|
world.SetAutoClearForces(true);
|
||||||
|
world.SetContactListener(&_contact_listener);
|
||||||
|
world.SetDebugDraw(&_debug_draw);
|
||||||
|
}
|
||||||
|
|
||||||
void DrawPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color) override{
|
void PyWorld::_register(VM* vm, PyObject* mod, PyObject* type){
|
||||||
}
|
|
||||||
|
|
||||||
void DrawSolidPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color) override{
|
|
||||||
}
|
|
||||||
|
|
||||||
void DrawCircle(const b2Vec2& center, float radius, const b2Color& color) override{
|
|
||||||
}
|
|
||||||
|
|
||||||
void DrawSolidCircle(const b2Vec2& center, float radius, const b2Vec2& axis, const b2Color& color) override{
|
|
||||||
}
|
|
||||||
|
|
||||||
void DrawSegment(const b2Vec2& p1, const b2Vec2& p2, const b2Color& color) override{
|
|
||||||
}
|
|
||||||
|
|
||||||
void DrawTransform(const b2Transform& xf) override{
|
|
||||||
}
|
|
||||||
|
|
||||||
void DrawPoint(const b2Vec2& p, float size, const b2Color& color) override{
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class PyContactListener : public b2ContactListener{
|
|
||||||
VM* vm;
|
|
||||||
public:
|
|
||||||
PyContactListener(VM* vm): vm(vm){}
|
|
||||||
|
|
||||||
void _contact_f(b2Contact* contact, StrName name){
|
|
||||||
auto a = contact->GetFixtureA()->GetBody()->GetUserData().pointer;
|
|
||||||
auto b = contact->GetFixtureB()->GetBody()->GetUserData().pointer;
|
|
||||||
Body* bodyA = reinterpret_cast<Body*>(a);
|
|
||||||
Body* bodyB = reinterpret_cast<Body*>(b);
|
|
||||||
PyObject* self;
|
|
||||||
PyObject* f;
|
|
||||||
f = vm->get_unbound_method(bodyA->obj, name, &self, false);
|
|
||||||
if(f != nullptr) vm->call_method(self, f, VAR_T(PyBody, bodyB));
|
|
||||||
f = vm->get_unbound_method(bodyB->obj, name, &self, false);
|
|
||||||
if(f != nullptr) vm->call_method(self, f, VAR_T(PyBody, bodyA));
|
|
||||||
}
|
|
||||||
|
|
||||||
void BeginContact(b2Contact* contact) override {
|
|
||||||
DEF_SNAME(on_contact_begin);
|
|
||||||
_contact_f(contact, on_contact_begin);
|
|
||||||
}
|
|
||||||
|
|
||||||
void EndContact(b2Contact* contact) override {
|
|
||||||
DEF_SNAME(on_contact_end);
|
|
||||||
_contact_f(contact, on_contact_end);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// implement placement VAR_T...!!!!
|
|
||||||
struct PyWorld {
|
|
||||||
PY_CLASS(PyWorld, box2d, World)
|
|
||||||
|
|
||||||
// this object is too large, so we use unique_ptr
|
|
||||||
std::unique_ptr<b2World> world;
|
|
||||||
std::unique_ptr<PyContactListener> _contact_listener;
|
|
||||||
std::unique_ptr<PyDebugDraw> _debug_draw;
|
|
||||||
|
|
||||||
PyWorld(VM* vm):
|
|
||||||
world(new b2World(b2Vec2(0, 0))),
|
|
||||||
_contact_listener(new PyContactListener(vm)),
|
|
||||||
_debug_draw(new PyDebugDraw(vm)){
|
|
||||||
world->SetAllowSleeping(true);
|
|
||||||
world->SetAutoClearForces(true);
|
|
||||||
world->SetContactListener(_contact_listener.get());
|
|
||||||
world->SetDebugDraw(_debug_draw.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
PyWorld(const PyWorld&) = delete;
|
|
||||||
PyWorld& operator=(const PyWorld&) = delete;
|
|
||||||
|
|
||||||
static void _register(VM* vm, PyObject* mod, PyObject* type){
|
|
||||||
vm->bind(type, "__new__(cls)", [](VM* vm, ArgsView args){
|
vm->bind(type, "__new__(cls)", [](VM* vm, ArgsView args){
|
||||||
return VAR_T(PyWorld, PyWorld(vm));
|
return VAR_T(PyWorld, PyWorld(vm));
|
||||||
});
|
});
|
||||||
@ -125,20 +50,19 @@ struct PyWorld {
|
|||||||
// gravity
|
// gravity
|
||||||
vm->bind_property(type, "gravity", "vec2", [](VM* vm, ArgsView args){
|
vm->bind_property(type, "gravity", "vec2", [](VM* vm, ArgsView args){
|
||||||
PyWorld& self = _CAST(PyWorld&, args[0]);
|
PyWorld& self = _CAST(PyWorld&, args[0]);
|
||||||
return VAR(self.world->GetGravity());
|
return VAR(self.world.GetGravity());
|
||||||
}, [](VM* vm, ArgsView args){
|
}, [](VM* vm, ArgsView args){
|
||||||
PyWorld& self = _CAST(PyWorld&, args[0]);
|
PyWorld& self = _CAST(PyWorld&, args[0]);
|
||||||
self.world->SetGravity(CAST(b2Vec2, args[1]));
|
self.world.SetGravity(CAST(b2Vec2, args[1]));
|
||||||
return vm->None;
|
return vm->None;
|
||||||
});
|
});
|
||||||
|
|
||||||
vm->bind(type, "get_bodies(self) -> list[Body]", [](VM* vm, ArgsView args){
|
vm->bind(type, "get_bodies(self) -> list[Body]", [](VM* vm, ArgsView args){
|
||||||
PyWorld& self = _CAST(PyWorld&, args[0]);
|
PyWorld& self = _CAST(PyWorld&, args[0]);
|
||||||
List list;
|
List list;
|
||||||
b2Body* p = self.world->GetBodyList();
|
b2Body* p = self.world.GetBodyList();
|
||||||
while(p != nullptr){
|
while(p != nullptr){
|
||||||
Body* body = (Body*)p->GetUserData().pointer;
|
list.push_back(get_body_object(p));
|
||||||
list.push_back(VAR_T(PyBody, body));
|
|
||||||
p = p->GetNext();
|
p = p->GetNext();
|
||||||
}
|
}
|
||||||
return VAR(std::move(list));
|
return VAR(std::move(list));
|
||||||
@ -150,7 +74,7 @@ struct PyWorld {
|
|||||||
b2Vec2 start = CAST(b2Vec2, args[1]);
|
b2Vec2 start = CAST(b2Vec2, args[1]);
|
||||||
b2Vec2 end = CAST(b2Vec2, args[2]);
|
b2Vec2 end = CAST(b2Vec2, args[2]);
|
||||||
MyRayCastCallback callback(vm);
|
MyRayCastCallback callback(vm);
|
||||||
self.world->RayCast(&callback, start, end);
|
self.world.RayCast(&callback, start, end);
|
||||||
return VAR(std::move(callback.result));
|
return VAR(std::move(callback.result));
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -161,7 +85,7 @@ struct PyWorld {
|
|||||||
aabb.lowerBound = CAST(b2Vec2, args[1]);
|
aabb.lowerBound = CAST(b2Vec2, args[1]);
|
||||||
aabb.upperBound = CAST(b2Vec2, args[2]);
|
aabb.upperBound = CAST(b2Vec2, args[2]);
|
||||||
MyBoxCastCallback callback(vm);
|
MyBoxCastCallback callback(vm);
|
||||||
self.world->QueryAABB(&callback, aabb);
|
self.world.QueryAABB(&callback, aabb);
|
||||||
return VAR(std::move(callback.result));
|
return VAR(std::move(callback.result));
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -174,21 +98,36 @@ struct PyWorld {
|
|||||||
|
|
||||||
auto f = [](VM* vm, b2Body* p, StrName name){
|
auto f = [](VM* vm, b2Body* p, StrName name){
|
||||||
while(p != nullptr){
|
while(p != nullptr){
|
||||||
Body* body = (Body*)p->GetUserData().pointer;
|
PyObject* body_obj = get_body_object(p);
|
||||||
vm->call_method(body->obj, name);
|
PyBody& body = _CAST(PyBody&, body_obj);
|
||||||
|
if(body.node_like != vm->None){
|
||||||
|
vm->call_method(body.node_like, name);
|
||||||
|
}
|
||||||
p = p->GetNext();
|
p = p->GetNext();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
DEF_SNAME(on_box2d_pre_step);
|
DEF_SNAME(on_box2d_pre_step);
|
||||||
DEF_SNAME(on_box2d_post_step);
|
DEF_SNAME(on_box2d_post_step);
|
||||||
f(vm, self.world->GetBodyList(), on_box2d_pre_step);
|
f(vm, self.world.GetBodyList(), on_box2d_pre_step);
|
||||||
self.world->Step(dt, velocity_iterations, position_iterations);
|
self.world.Step(dt, velocity_iterations, position_iterations);
|
||||||
f(vm, self.world->GetBodyList(), on_box2d_post_step);
|
f(vm, self.world.GetBodyList(), on_box2d_post_step);
|
||||||
return vm->None;
|
return vm->None;
|
||||||
});
|
});
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace imbox2d
|
vm->bind(type, "debug_draw(self, flags: int)", [](VM* vm, ArgsView args){
|
||||||
} // namespace pkpy
|
PyWorld& self = _CAST(PyWorld&, args[0]);
|
||||||
|
int flags = CAST(int, args[1]);
|
||||||
|
self._debug_draw.SetFlags(flags);
|
||||||
|
self.world.DebugDraw();
|
||||||
|
return vm->None;
|
||||||
|
});
|
||||||
|
|
||||||
|
vm->bind(type, "set_debug_draw(self, draw: _DrawLike)", [](VM* vm, ArgsView args){
|
||||||
|
PyWorld& self = _CAST(PyWorld&, args[0]);
|
||||||
|
self._debug_draw.draw_like = args[1];
|
||||||
|
return vm->None;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace imbox2d
|
@ -2,12 +2,6 @@
|
|||||||
|
|
||||||
namespace pkpy{
|
namespace pkpy{
|
||||||
|
|
||||||
void add_module_box2d(VM *vm){
|
|
||||||
PyObject* mod = vm->new_module("box2d");
|
|
||||||
imbox2d::PyBody::register_class(vm, mod);
|
|
||||||
imbox2d::PyWorld::register_class(vm, mod);
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace imbox2d{
|
namespace imbox2d{
|
||||||
|
|
||||||
|
|
||||||
|
@ -164,4 +164,10 @@ struct is_pod {
|
|||||||
static constexpr bool value = std::is_trivially_copyable_v<T> && std::is_standard_layout_v<T>;
|
static constexpr bool value = std::is_trivially_copyable_v<T> && std::is_standard_layout_v<T>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define PK_ALWAYS_PASS_BY_POINTER(T) \
|
||||||
|
T(const T&) = delete; \
|
||||||
|
T& operator=(const T&) = delete; \
|
||||||
|
T(T&&) = delete; \
|
||||||
|
T& operator=(T&&) = delete;
|
||||||
|
|
||||||
} // namespace pkpy
|
} // namespace pkpy
|
||||||
|
@ -107,6 +107,8 @@ struct FrameId{
|
|||||||
typedef void(*PrintFunc)(VM*, const Str&);
|
typedef void(*PrintFunc)(VM*, const Str&);
|
||||||
|
|
||||||
class VM {
|
class VM {
|
||||||
|
PK_ALWAYS_PASS_BY_POINTER(VM)
|
||||||
|
|
||||||
VM* vm; // self reference for simplify code
|
VM* vm; // self reference for simplify code
|
||||||
public:
|
public:
|
||||||
ManagedHeap heap;
|
ManagedHeap heap;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user