Skip to content
This repository has been archived by the owner on Dec 29, 2024. It is now read-only.

Add back CallableCustom for module builds #169

Merged
merged 2 commits into from
Oct 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,15 @@ Release Builds
- [⚙️ GDExtension LuaJIT](https://github.com/WeaselGames/godot_luaAPI/releases/latest/download/gdextension-LuaJIT.zip)
- [🐧 Linux Editor](https://github.com/WeaselGames/godot_luaAPI/releases/latest/download/linux-editor.zip)
- [🐧 Linux Editor LuaJIT](https://github.com/WeaselGames/godot_luaAPI/releases/latest/download/linux-editor-luajit.zip)
- [🐧 Linux Editor Mono](https://github.com/WeaselGames/godot_luaAPI/releases/latest/download/linux-editor.zip)
- [🎨 Windows Editor](https://github.com/WeaselGames/godot_luaAPI/releases/latest/download/windows-editor.zip)
- [🎨 Windows Editor LuaJIT](https://github.com/WeaselGames/godot_luaAPI/releases/latest/download/windows-editor-luajit.zip)
- [🎨 Windows Editor Mono](https://github.com/WeaselGames/godot_luaAPI/releases/latest/download/windows-editor-mono.zip)
- [🍎 MacOS Editor](https://github.com/WeaselGames/godot_luaAPI/releases/latest/download/macos-editor.zip)
- [🍎 MacOS Editor LuaJIT](https://github.com/WeaselGames/godot_luaAPI/releases/latest/download/macos-editor-luajit.zip)
- [🗜️ Export Templates](https://github.com/WeaselGames/godot_luaAPI/releases/latest/download/export-templates.tpz)
- [🍎 MacOS Editor Mono](https://github.com/WeaselGames/godot_luaAPI/releases/latest/download/macos-editor-mono.zip)
- [🗜️ Export Templates](https://github.com/WeaselGames/godot_luaAPI/releases/latest/download/export-templates.zip)
- [🗜️ Mono Export Templates](https://github.com/WeaselGames/godot_luaAPI/releases/latest/download/export-templates-mono.zip)
- For previous versions see [releases](https://github.com/WeaselGames/godot_luaAPI/releases)

Compiling
Expand Down
4 changes: 4 additions & 0 deletions src/classes/luaAPI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ void LuaAPI::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_registry_value", "Name"), &LuaAPI::getRegistryValue);
ClassDB::bind_method(D_METHOD("set_registry_value", "Name", "var"), &LuaAPI::setRegistryValue);
ClassDB::bind_method(D_METHOD("call_function", "LuaFunctionName", "Args"), &LuaAPI::callFunction);
#ifdef LAPI_GDEXTENSION
ClassDB::bind_method(D_METHOD("call_function_ref", "Args", "LuaFunctionRef"), &LuaAPI::callFunctionRef);
#endif
ClassDB::bind_method(D_METHOD("function_exists", "LuaFunctionName"), &LuaAPI::luaFunctionExists);

ClassDB::bind_method(D_METHOD("new_coroutine"), &LuaAPI::newCoroutine);
Expand Down Expand Up @@ -123,6 +125,7 @@ Variant LuaAPI::callFunction(String functionName, Array args) {
return state.callFunction(functionName, args);
}

#ifdef LAPI_GDEXTENSION
// Invokes the passed lua reference
Variant LuaAPI::callFunctionRef(Array args, int funcRef) {
lua_pushcfunction(lState, LuaState::luaErrorHandler);
Expand All @@ -147,6 +150,7 @@ Variant LuaAPI::callFunctionRef(Array args, int funcRef) {
lua_pop(lState, 1);
return toReturn;
}
#endif

// Calls LuaState::pushGlobalVariant()
Ref<LuaError> LuaAPI::pushGlobalVariant(String name, Variant var) {
Expand Down
2 changes: 2 additions & 0 deletions src/classes/luaAPI.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,9 @@ class LuaAPI : public RefCounted {

Variant pullVariant(String name);
Variant callFunction(String functionName, Array args);
#ifdef LAPI_GDEXTENSION
Variant callFunctionRef(Array args, int funcRef);
#endif

Variant getRegistryValue(String name);
Ref<LuaError> setRegistryValue(String name, Variant var);
Expand Down
97 changes: 97 additions & 0 deletions src/classes/luaCallable.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
#ifndef LAPI_GDEXTENSION

#include "luaCallable.h"
#include "luaAPI.h"

#include "core/templates/hashfuncs.h"

// I used "GDScriptLambdaCallable" as a template for this
LuaCallable::LuaCallable(Ref<LuaAPI> p_obj, int ref, lua_State *p_state) {
obj = p_obj;
funcRef = ref;
state = p_state;
h = (uint32_t)hash_djb2_one_64((uint64_t)this);
}

LuaCallable::~LuaCallable() {
print_line("LuaCallable::~LuaCallable()");
luaL_unref(state, LUA_REGISTRYINDEX, funcRef);
}

bool LuaCallable::compare_equal(const CallableCustom *p_a, const CallableCustom *p_b) {
// Lua callables are only compared by reference.
return p_a == p_b;
}

bool LuaCallable::compare_less(const CallableCustom *p_a, const CallableCustom *p_b) {
// Lua callables are only compared by reference.
return p_a < p_b;
}

CallableCustom::CompareEqualFunc LuaCallable::get_compare_equal_func() const {
return compare_equal;
}

CallableCustom::CompareLessFunc LuaCallable::get_compare_less_func() const {
return compare_less;
}

ObjectID LuaCallable::get_object() const {
return obj->get_instance_id();
}

String LuaCallable::get_as_text() const {
// I dont know of a way to get a useful name from the function
// For now we are just using the callables hash.
return vformat("luaCallable 0x%X", h);
}

lua_State *LuaCallable::getLuaState() const {
return state;
}

uint32_t LuaCallable::hash() const {
return h;
}

void LuaCallable::call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const {
lua_pushcfunction(state, LuaState::luaErrorHandler);

// Getting the lua function via the reference stored in funcRef
lua_rawgeti(state, LUA_REGISTRYINDEX, funcRef);

// ------------------
// This is a hack to match the API with the GDExtension Callable workaround
if (p_argcount != 1 || p_arguments[0]->get_type() != Variant::Type::ARRAY) {
r_return_value = LuaError::newError("LuaCallable arguments must be supplied with a Godot Array", LuaError::ERR_TYPE);
return;
}

Array args = p_arguments[0]->operator Array();
for (int i = 0; i < args.size(); i++) {
LuaState::pushVariant(state, args[i]);
}

p_argcount = args.size();
// ------------------

// Push all the argument on to the stack
// for (int i = 0; i < p_argcount; i++) {
// LuaState::pushVariant(state, *p_arguments[i]);
// }

// execute the function using a protected call.
int ret = lua_pcall(state, p_argcount, 1, -2 - p_argcount);
if (ret != LUA_OK) {
r_return_value = LuaState::handleError(state, ret);
} else {
r_return_value = LuaState::getVariant(state, -1);
}

lua_pop(state, 1);
}

int LuaCallable::getFuncRef() {
return funcRef;
}
#endif
43 changes: 43 additions & 0 deletions src/classes/luaCallable.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#ifndef LAPI_GDEXTENSION

#ifndef LUACALLABLE_H
#define LUACALLABLE_H

#include "core/object/ref_counted.h"
#include "core/variant/callable.h"

#include <classes/luaAPI.h>

#include <lua/lua.hpp>

#ifdef LAPI_GDEXTENSION
using namespace godot;
#endif

class LuaCallable : public CallableCustom {
static bool compare_equal(const CallableCustom *p_a, const CallableCustom *p_b);
static bool compare_less(const CallableCustom *p_a, const CallableCustom *p_b);
uint32_t h;

public:
uint32_t hash() const override;
String get_as_text() const override;
CompareEqualFunc get_compare_equal_func() const override;
CompareLessFunc get_compare_less_func() const override;
ObjectID get_object() const override;
lua_State *getLuaState() const;
void call(const Variant **p_argument, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override;

int getFuncRef();

LuaCallable(Ref<LuaAPI> obj, int ref, lua_State *p_state);
~LuaCallable() override;

private:
int funcRef;
Ref<LuaAPI> obj;
lua_State *state = nullptr;
};

#endif
#endif
21 changes: 20 additions & 1 deletion src/luaState.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@
#include <classes/luaCoroutine.h>
#include <classes/luaTuple.h>

#ifndef LAPI_GDXTENSION
#include <classes/luaCallable.h>
#endif

#include <util.h>

void LuaState::setState(lua_State *state, LuaAPI *api, bool bindAPI) {
Expand Down Expand Up @@ -489,9 +493,17 @@ Ref<LuaError> LuaState::pushVariant(lua_State *state, Variant var) {
// If the type being pushed is a lua function ref, push the ref instead.
#ifndef LAPI_GDEXTENSION
Ref<LuaAPI> callObj = Object::cast_to<LuaAPI>(callable.get_object());
CallableCustom *custom = callable.get_custom();
LuaCallable *luaCallable = dynamic_cast<LuaCallable *>(custom);
if (luaCallable != nullptr) {
lua_rawgeti(state, LUA_REGISTRYINDEX, luaCallable->getFuncRef());
if (luaCallable->getLuaState() != state) {
lua_xmove(luaCallable->getLuaState(), state, 1);
}
break;
}
#else
Ref<LuaAPI> callObj = dynamic_cast<LuaAPI *>(callable.get_object());
#endif
if (callObj.is_valid() && (String)callable.get_method() == "call_function_ref") {
Array argBinds = callable.get_bound_arguments();
if (argBinds.size() == 1) {
Expand All @@ -503,6 +515,7 @@ Ref<LuaError> LuaState::pushVariant(lua_State *state, Variant var) {
break;
}
}
#endif

// A work around to preserve ref count of CallableCustoms
Ref<LuaCallableExtra> callableCustom;
Expand Down Expand Up @@ -582,10 +595,16 @@ Variant LuaState::getVariant(lua_State *state, int index) {
break;
}
case LUA_TFUNCTION: {
// Put function on the top of the stack and get a ref to it. This will create a copy of the function.
lua_pushvalue(state, index);
#ifndef LAPI_GDEXTENSION
LuaCallable *callable = memnew(LuaCallable(Ref<LuaAPI>(getAPI(state)), luaL_ref(state, LUA_REGISTRYINDEX), state));
result = Callable(callable);
#else
Array binds;
binds.push_back(luaL_ref(state, LUA_REGISTRYINDEX));
result = Callable(getAPI(state), "call_function_ref").bindv(binds);
#endif
break;
}
case LUA_TTHREAD: {
Expand Down