mirror of
https://github.com/love2d/love.git
synced 2026-08-16 00:02:12 +02:00
Add Data:getFFIPointer. Similar to Data:getPointer but returns a cdata pointer directly (or nil if the FFI isn't available).
It should be preferred instead of Data:getPointer because the latter uses lightuserdata which can't store more all possible memory addresses on some new arm64 architectures, when LuaJIT is used.
This commit is contained in:
@@ -39,6 +39,7 @@ static const luaL_Reg w_ByteData_functions[] =
|
||||
int luaopen_bytedata(lua_State *L)
|
||||
{
|
||||
luax_register_type(L, &ByteData::type, w_Data_functions, w_ByteData_functions, nullptr);
|
||||
love::data::luax_rundatawrapper(L, ByteData::type);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -63,7 +63,9 @@ static const luaL_Reg w_CompressedData_functions[] =
|
||||
|
||||
extern "C" int luaopen_compresseddata(lua_State *L)
|
||||
{
|
||||
return luax_register_type(L, &CompressedData::type, w_Data_functions, w_CompressedData_functions, nullptr);
|
||||
int ret = luax_register_type(L, &CompressedData::type, w_Data_functions, w_CompressedData_functions, nullptr);
|
||||
love::data::luax_rundatawrapper(L, CompressedData::type);
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // data
|
||||
|
||||
@@ -20,6 +20,11 @@
|
||||
|
||||
#include "wrap_Data.h"
|
||||
|
||||
// Put the Lua code directly into a raw string literal.
|
||||
static const char data_lua[] =
|
||||
#include "wrap_Data.lua"
|
||||
;
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace data
|
||||
@@ -44,6 +49,13 @@ int w_Data_getPointer(lua_State *L)
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Placeholder, overridden by the FFI code when the FFI is available.
|
||||
int w_Data_getFFIPointer(lua_State *L)
|
||||
{
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_Data_getSize(lua_State *L)
|
||||
{
|
||||
Data *t = luax_checkdata(L, 1);
|
||||
@@ -51,18 +63,40 @@ int w_Data_getSize(lua_State *L)
|
||||
return 1;
|
||||
}
|
||||
|
||||
// C functions in a struct, necessary for the FFI versions of Data methods.
|
||||
struct FFI_Data
|
||||
{
|
||||
void *(*getFFIPointer)(Proxy *p);
|
||||
};
|
||||
|
||||
static FFI_Data ffifuncs =
|
||||
{
|
||||
[](Proxy *p) -> void * // getFFIPointer
|
||||
{
|
||||
auto data = luax_ffi_checktype<Data>(p);
|
||||
return data != nullptr ? data->getData() : nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
const luaL_Reg w_Data_functions[] =
|
||||
{
|
||||
{ "getString", w_Data_getString },
|
||||
{ "getPointer", w_Data_getPointer },
|
||||
{ "getFFIPointer", w_Data_getFFIPointer },
|
||||
{ "getSize", w_Data_getSize },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
void luax_rundatawrapper(lua_State *L, const love::Type &type)
|
||||
{
|
||||
luax_runwrapper(L, data_lua, sizeof(data_lua), "Data.lua", type, &ffifuncs);
|
||||
}
|
||||
|
||||
int luaopen_data(lua_State *L)
|
||||
{
|
||||
luax_register_type(L, &Data::type, w_Data_functions, nullptr);
|
||||
return 0;
|
||||
int n = luax_register_type(L, &Data::type, w_Data_functions, nullptr);
|
||||
luax_rundatawrapper(L, Data::type);
|
||||
return n;
|
||||
}
|
||||
|
||||
} // data
|
||||
|
||||
@@ -29,6 +29,7 @@ namespace love
|
||||
namespace data
|
||||
{
|
||||
|
||||
void luax_rundatawrapper(lua_State *L, const love::Type &type);
|
||||
Data *luax_checkdata(lua_State *L, int idx);
|
||||
int luaopen_data(lua_State *L);
|
||||
extern const luaL_Reg w_Data_functions[];
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
R"luastring"--(
|
||||
-- DO NOT REMOVE THE ABOVE LINE. It is used to load this file as a C++ string.
|
||||
-- There is a matching delimiter at the bottom of the file.
|
||||
|
||||
--[[
|
||||
Copyright (c) 2006-2019 LOVE Development Team
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
--]]
|
||||
|
||||
local Data_mt, ffifuncspointer_str = ...
|
||||
local Data = Data_mt.__index
|
||||
|
||||
local type, error = type, error
|
||||
|
||||
if type(jit) ~= "table" then return end
|
||||
|
||||
local status, ffi = pcall(require, "ffi")
|
||||
if not status then return end
|
||||
|
||||
pcall(ffi.cdef, [[
|
||||
typedef struct Proxy Proxy;
|
||||
|
||||
typedef struct FFI_Data
|
||||
{
|
||||
void *(*getFFIPointer)(Proxy *p);
|
||||
} FFI_Data;
|
||||
]])
|
||||
|
||||
local ffifuncs = ffi.cast("const FFI_Data **", ffifuncspointer_str)[0]
|
||||
|
||||
-- Overwrite placeholder method with the FFI implementation.
|
||||
|
||||
function Data:getFFIPointer()
|
||||
-- TODO: This should ideally be handled inside the C function
|
||||
if self == nil then error("bad argument #1 to 'getFFIPointer' (Data expected, got no value)", 2) end
|
||||
return ffifuncs.getFFIPointer(self)
|
||||
end
|
||||
|
||||
-- DO NOT REMOVE THE NEXT LINE. It is used to load this file as a C++ string.
|
||||
--)luastring"--"
|
||||
@@ -39,6 +39,7 @@ static const luaL_Reg w_DataView_functions[] =
|
||||
int luaopen_dataview(lua_State *L)
|
||||
{
|
||||
luax_register_type(L, &DataView::type, w_Data_functions, w_DataView_functions, nullptr);
|
||||
love::data::luax_rundatawrapper(L, DataView::type);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -66,7 +66,9 @@ static const luaL_Reg w_FileData_functions[] =
|
||||
|
||||
extern "C" int luaopen_filedata(lua_State *L)
|
||||
{
|
||||
return luax_register_type(L, &FileData::type, data::w_Data_functions, w_FileData_functions, nullptr);
|
||||
int ret = luax_register_type(L, &FileData::type, data::w_Data_functions, w_FileData_functions, nullptr);
|
||||
love::data::luax_rundatawrapper(L, FileData::type);
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // filesystem
|
||||
|
||||
@@ -141,7 +141,9 @@ const luaL_Reg w_GlyphData_functions[] =
|
||||
|
||||
extern "C" int luaopen_glyphdata(lua_State *L)
|
||||
{
|
||||
return luax_register_type(L, &GlyphData::type, data::w_Data_functions, w_GlyphData_functions, nullptr);
|
||||
int ret = luax_register_type(L, &GlyphData::type, data::w_Data_functions, w_GlyphData_functions, nullptr);
|
||||
love::data::luax_rundatawrapper(L, GlyphData::type);
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // font
|
||||
|
||||
@@ -116,7 +116,9 @@ static const luaL_Reg w_CompressedImageData_functions[] =
|
||||
|
||||
extern "C" int luaopen_compressedimagedata(lua_State *L)
|
||||
{
|
||||
return luax_register_type(L, &CompressedImageData::type, data::w_Data_functions, w_CompressedImageData_functions, nullptr);
|
||||
int ret = luax_register_type(L, &CompressedImageData::type, data::w_Data_functions, w_CompressedImageData_functions, nullptr);
|
||||
love::data::luax_rundatawrapper(L, CompressedImageData::type);
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // image
|
||||
|
||||
@@ -510,20 +510,8 @@ extern "C" int luaopen_imagedata(lua_State *L)
|
||||
|
||||
int ret = luax_register_type(L, &ImageData::type, data::w_Data_functions, w_ImageData_functions, nullptr);
|
||||
|
||||
luax_gettypemetatable(L, ImageData::type);
|
||||
|
||||
// Load and execute ImageData.lua, sending the metatable and the ffi
|
||||
// functions struct pointer as arguments.
|
||||
if (lua_istable(L, -1))
|
||||
{
|
||||
luaL_loadbuffer(L, imagedata_lua, sizeof(imagedata_lua), "ImageData.lua");
|
||||
lua_pushvalue(L, -2);
|
||||
lua_pushlightuserdata(L, &ffifuncs);
|
||||
lua_call(L, 2, 0);
|
||||
}
|
||||
|
||||
// Pop the metatable.
|
||||
lua_pop(L, 1);
|
||||
love::data::luax_rundatawrapper(L, ImageData::type);
|
||||
luax_runwrapper(L, imagedata_lua, sizeof(imagedata_lua), "ImageData.lua", ImageData::type, &ffifuncs);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
--]]
|
||||
|
||||
local ImageData_mt, ffifuncspointer = ...
|
||||
local ImageData_mt, ffifuncspointer_str = ...
|
||||
local ImageData = ImageData_mt.__index
|
||||
|
||||
local tonumber, assert, error = tonumber, assert, error
|
||||
@@ -103,7 +103,7 @@ struct ImageData_Pixel_RG32F { float r, g; };
|
||||
struct ImageData_Pixel_RGBA32F { float r, g, b, a; };
|
||||
]])
|
||||
|
||||
local ffifuncs = ffi.cast("FFI_ImageData *", ffifuncspointer)
|
||||
local ffifuncs = ffi.cast("FFI_ImageData **", ffifuncspointer_str)[0]
|
||||
|
||||
local conversions = {
|
||||
r8 = {
|
||||
|
||||
@@ -126,22 +126,14 @@ static FFI_RandomGenerator ffifuncs =
|
||||
{
|
||||
[](Proxy *p) -> double // random()
|
||||
{
|
||||
// FIXME: We need better type-checking...
|
||||
if (p == nullptr || p->object == nullptr || p->type == nullptr || !p->type->isa(RandomGenerator::type))
|
||||
return 0.0;
|
||||
|
||||
RandomGenerator *rng = (RandomGenerator *) p->object;
|
||||
return rng->random();
|
||||
auto rng = luax_ffi_checktype<RandomGenerator>(p);
|
||||
return rng != nullptr ? rng->random() : 0.0;
|
||||
},
|
||||
|
||||
[](Proxy *p, double stdddev, double mean) -> double // randomNormal
|
||||
{
|
||||
// FIXME: We need better type-checking...
|
||||
if (p == nullptr || p->object == nullptr || p->type == nullptr || !p->type->isa(RandomGenerator::type))
|
||||
return 0.0;
|
||||
|
||||
RandomGenerator *rng = (RandomGenerator *) p->object;
|
||||
return rng->randomNormal(stdddev) + mean;
|
||||
auto rng = luax_ffi_checktype<RandomGenerator>(p);
|
||||
return rng != nullptr ? (rng->randomNormal(stdddev) + mean) : 0.0;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -160,20 +152,7 @@ extern "C" int luaopen_randomgenerator(lua_State *L)
|
||||
{
|
||||
int n = luax_register_type(L, &RandomGenerator::type, w_RandomGenerator_functions, nullptr);
|
||||
|
||||
luax_gettypemetatable(L, RandomGenerator::type);
|
||||
|
||||
// Load and execute wrap_RandomGenerator.lua, sending the metatable and the
|
||||
// ffi functions struct pointer as arguments.
|
||||
if (lua_istable(L, -1))
|
||||
{
|
||||
luaL_loadbuffer(L, randomgenerator_lua, sizeof(randomgenerator_lua), "wrap_RandomGenerator.lua");
|
||||
lua_pushvalue(L, -2);
|
||||
lua_pushlightuserdata(L, &ffifuncs);
|
||||
lua_call(L, 2, 0);
|
||||
}
|
||||
|
||||
// Pop the metatable.
|
||||
lua_pop(L, 1);
|
||||
luax_runwrapper(L, randomgenerator_lua, sizeof(randomgenerator_lua), "RandomGenerator.lua", RandomGenerator::type, &ffifuncs);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
--]]
|
||||
|
||||
local RandomGenerator_mt, ffifuncspointer = ...
|
||||
local RandomGenerator_mt, ffifuncspointer_str = ...
|
||||
local RandomGenerator = RandomGenerator_mt.__index
|
||||
|
||||
local type, tonumber, error = type, tonumber, error
|
||||
@@ -67,7 +67,7 @@ typedef struct FFI_RandomGenerator
|
||||
} FFI_RandomGenerator;
|
||||
]])
|
||||
|
||||
local ffifuncs = ffi.cast("FFI_RandomGenerator *", ffifuncspointer)
|
||||
local ffifuncs = ffi.cast("FFI_RandomGenerator **", ffifuncspointer_str)[0]
|
||||
|
||||
|
||||
-- Overwrite some regular love.math functions with FFI implementations.
|
||||
|
||||
@@ -148,18 +148,8 @@ extern "C" int luaopen_sounddata(lua_State *L)
|
||||
{
|
||||
int ret = luax_register_type(L, &SoundData::type, data::w_Data_functions, w_SoundData_functions, nullptr);
|
||||
|
||||
luax_gettypemetatable(L, SoundData::type);
|
||||
|
||||
// Load and execute SoundData.lua, sending the metatable as an argument.
|
||||
if (lua_istable(L, -1))
|
||||
{
|
||||
luaL_loadbuffer(L, sounddata_lua, sizeof(sounddata_lua), "SoundData.lua");
|
||||
lua_pushvalue(L, -2);
|
||||
lua_call(L, 1, 0);
|
||||
}
|
||||
|
||||
// Pop the metatable.
|
||||
lua_pop(L, 1);
|
||||
love::data::luax_rundatawrapper(L, SoundData::type);
|
||||
luax_runwrapper(L, sounddata_lua, sizeof(sounddata_lua), "SoundData.lua", SoundData::type, nullptr);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user