Skip to content

Instantly share code, notes, and snippets.

@ZumiKua
Last active November 6, 2025 19:23
Show Gist options
  • Select an option

  • Save ZumiKua/5b331840163b5a0308fc915ef9902adb to your computer and use it in GitHub Desktop.

Select an option

Save ZumiKua/5b331840163b5a0308fc915ef9902adb to your computer and use it in GitHub Desktop.
// luajittest.cpp : This file contains the 'main' function. Program execution begins and ends there.
//
#include <iostream>
#include <string>
#include "lua.hpp"
#include "LuaJIT/src/lj_obj.h"
#include "LuaJIT/src/lj_ctype.h"
typedef struct { int a, b; } Object;
Object* createObject() {
printf("Create\n");
return new Object();
}
bool deleted = false;
void deleteObject(Object* ptr) {
printf("Delete\n");
deleted = true;
delete ptr;
}
typedef int (*callback_type)(int a);
callback_type callback;
void addCallback(int (*invoker)(int a)) {
printf("Callback set\n");
callback = invoker;
}
#define REGISTER(L, s) registerSymbol(L, #s, s)
static void registerSymbol(lua_State* L, const char* str, void* ptr) {
lua_pushstring(L, str);
lua_pushlightuserdata(L, ptr);
lua_settable(L, -3);
}
void getfieldtable(lua_State* L, const char* name, int tableIdx) {
lua_newtable(L);
lua_pushstring(L, name);
lua_pushvalue(L, -2);
lua_settable(L, tableIdx);
}
static void registerAllSymbols(lua_State* L) {
getfieldtable(L, "_CLIBS", LUA_REGISTRYINDEX);
lua_pushstring(L, "TEST");
lua_newtable(L);
REGISTER(L, createObject);
REGISTER(L, deleteObject);
REGISTER(L, addCallback);
lua_settable(L, -3);
lua_pop(L, 1);
}
void load(lua_State* L, const char* code, const char* name) {
int top = lua_gettop(L);
int status = luaL_loadbuffer(L, code, strlen(code), name);
printf("%s", code);
if (status) {
throw std::runtime_error("Error loading lua string");
}
int r = lua_pcall(L, 0, LUA_MULTRET, 0);
int nresults = lua_gettop(L) - top;
if (r != 0) {
const char* str = lua_tostring(L, -1);
printf("%s", str);
}
lua_pop(L, nresults);
switch (r) {
case LUA_OK:
break;
case LUA_ERRRUN:
throw std::runtime_error("Runtime error while running LUA code.");
case LUA_ERRMEM:
throw std::runtime_error("Memory allocation error while running LUA code.");
case LUA_ERRERR:
throw std::runtime_error("Error in Error function.");
case LUA_ERRSYNTAX:
throw std::runtime_error("Syntax error in Lua code.");
default:
throw std::runtime_error(std::string("Unknow error while running LUA code (err code: ") +
std::to_string(r) + ")");
}
}
int main()
{
static int lualoader = 1;
lua_State* L = lua_open();
int n = lua_gettop(L);
luaopen_ffi(L);
lua_pushstring(L, "ffi");
lua_pushvalue(L, -2);
lua_settable(L, LUA_GLOBALSINDEX);
while (n < lua_gettop(L)) lua_pop(L, 1);
static const char* test = (
#include "test.lua"
);
registerAllSymbols(L);
load(L, test, "src:test.lua");
printf("before %d\n", deleted);
int i = 0;
lua_State* delete_L = nullptr;
while (i < 1000) {
lua_State* newL = lua_newthread(L);
printf("whild %d %d %x %x %x\n", i++, deleted, mref(G(L)->ctype_state, CTState)->L, L, newL);
bool oldDeleted = deleted;
if (luaL_dostring(newL, "local i = 1") != LUA_OK) {
fprintf(stderr, "Error executing Lua code: %s\n", lua_tostring(L, -1));
}
if (oldDeleted != deleted) {
delete_L = newL;
}
}
lua_gc(L, LUA_GCCOLLECT, 0);
printf("Callback %d\n", callback(1));
printf("IsWhite %d\n", iswhite(obj2gco(delete_L)));
printf("Finish\n");
lua_close(L);
return 0;
}
-- lualoader, R"EOF(--
--print("Hello, World!")
ffi.cdef [[
typedef struct { char opaque[?]; } Object;
Object* createObject();
void deleteObject(Object*);
void addCallback(int (*invoker)(int a));
]]
local C = ffi.load 'TEST'
local function foo()
local it = ffi.gc(C.createObject(), C.deleteObject);
end
local cb = function (num)
local t = foo();
return num + 1
end
foo();
C.addCallback(ffi.cast('int (*)(int a)', cb))
-- )EOF"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment