summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorruki <[email protected]>2019-11-01 00:50:39 +0800
committerruki <[email protected]>2019-10-31 23:03:54 +0800
commit56178606d872629cb3553bf912a742c84cf244e4 (patch)
treefd11ec3abab4cca7dc093f6d55b5c7c3ee40386f
parent7d47837062fba756f66e7bea313cb59f9a026477 (diff)
export ffi/malloc for windows
-rw-r--r--core/src/demo/xmake.lua5
-rw-r--r--core/src/xmake/ffi.c53
-rw-r--r--core/src/xmake/ffi.h46
-rw-r--r--core/src/xmake/machine.c4
-rw-r--r--core/src/xmake/makefile1
-rw-r--r--xmake/core/base/bytes.lua133
6 files changed, 218 insertions, 24 deletions
diff --git a/core/src/demo/xmake.lua b/core/src/demo/xmake.lua
index edd6adfdd..2e26afb6e 100644
--- a/core/src/demo/xmake.lua
+++ b/core/src/demo/xmake.lua
@@ -7,9 +7,6 @@ target("demo")
-- make as a binary
set_kind("binary")
- -- set basename of target file
- set_basename("xmake")
-
-- add defines
add_defines("__tb_prefix__=\"xmake\"")
@@ -49,6 +46,6 @@ target("demo")
-- copy target to the build directory
after_build(function (target)
- os.cp(target:targetfile(), "$(buildir)")
+ os.cp(target:targetfile(), "$(buildir)/xmake.exe")
end)
diff --git a/core/src/xmake/ffi.c b/core/src/xmake/ffi.c
new file mode 100644
index 000000000..a863e9489
--- /dev/null
+++ b/core/src/xmake/ffi.c
@@ -0,0 +1,53 @@
+/*!A cross-platform build utility based on Lua
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2015 - 2019, TBOOX Open Source Group.
+ *
+ * @author ruki
+ * @file ffi.c
+ *
+ */
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * includes
+ */
+#include "xmake.h"
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * extern
+ */
+__tb_extern_c_enter__
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * wrap and export interfaces for ffi
+ */
+__tb_export__ void* xm_ffi_malloc(unsigned long size)
+{
+ return (void*)tb_malloc((tb_size_t)size);
+}
+__tb_export__ void xm_ffi_free(void* data)
+{
+ tb_free(data);
+}
+tb_void_t xm_ffi_bind()
+{
+ // avoid to be optimized
+ tb_used(&xm_ffi_malloc);
+ tb_used(&xm_ffi_free);
+}
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * extern
+ */
+__tb_extern_c_leave__
diff --git a/core/src/xmake/ffi.h b/core/src/xmake/ffi.h
new file mode 100644
index 000000000..a9885e53b
--- /dev/null
+++ b/core/src/xmake/ffi.h
@@ -0,0 +1,46 @@
+/*!A cross-platform build utility based on Lua
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2015 - 2019, TBOOX Open Source Group.
+ *
+ * @author ruki
+ * @file ffi.h
+ *
+ */
+#ifndef XM_FFI_H
+#define XM_FFI_H
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * includes
+ */
+#include "prefix.h"
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * extern
+ */
+__tb_extern_c_enter__
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * interfaces
+ */
+
+/// bind ffi
+tb_void_t xm_ffi_bind(tb_noarg_t);
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * extern
+ */
+__tb_extern_c_leave__
+
+#endif
diff --git a/core/src/xmake/machine.c b/core/src/xmake/machine.c
index 4319023cc..c022ce6ab 100644
--- a/core/src/xmake/machine.c
+++ b/core/src/xmake/machine.c
@@ -29,6 +29,7 @@
* includes
*/
#include "xmake.h"
+#include "ffi.h"
#if defined(TB_CONFIG_OS_WINDOWS)
# include <windows.h>
# include <io.h>
@@ -692,6 +693,9 @@ xm_machine_ref_t xm_machine_init()
}
#endif
+ // bind ffi interfaces
+ xm_ffi_bind();
+
// ok
ok = tb_true;
diff --git a/core/src/xmake/makefile b/core/src/xmake/makefile
index b3028e984..269db0c0b 100644
--- a/core/src/xmake/makefile
+++ b/core/src/xmake/makefile
@@ -12,6 +12,7 @@ xmake_CONFIG = y
# core files
xmake_C_FILES += \
+ ffi \
xmake \
machine \
os/argv \
diff --git a/xmake/core/base/bytes.lua b/xmake/core/base/bytes.lua
index 9f5a9ead2..c92bb065f 100644
--- a/xmake/core/base/bytes.lua
+++ b/xmake/core/base/bytes.lua
@@ -29,46 +29,91 @@ local os = require("base/os")
-- define ffi interfaces
ffi.cdef[[
- void* malloc(size_t __size);
- void free(void *__ptr);
+ void* xm_ffi_malloc(unsigned long size);
+ void xm_ffi_free(void* data);
]]
-- new a bytes instance
--
--- new(size): allocates a buffer of given size
--- new(size, ptr [, manage]) : mounts buffer on existing storage (manage memory or not)
--- new(str): allocates a buffer from the given string
+-- bytes(size): allocates a buffer of given size
+-- bytes(size, ptr [, manage]): mounts buffer on existing storage (manage memory or not)
+-- bytes(str): mounts a buffer from the given string
+-- bytes(bytes, start, last): mounts a buffer from another one, with start/last limits
+-- bytes(bytes1, bytes2, bytes3, ...): allocates and concat buffer from list of byte buffers
+-- bytes(bytes): allocates a buffer from another one (strict replica, sharing memory)
--
-function _instance.new(arg1, arg2, arg3)
+function _instance.new(...)
+ local args = {...}
+ local arg1, arg2, arg3 = unpack(args)
local instance = table.inherit(_instance)
if type(arg1) == "number" then
local size = arg1
local ptr = arg2
if ptr then
- -- new(size, ptr [, manage]) : mounts buffer on existing storage (manage memory or not)
+ -- bytes(size, ptr [, manage]): mounts buffer on existing storage (manage memory or not)
local manage = arg3
if manage then
- instance._CDATA = ffi.gc(ffi.cast("unsigned char*", ptr), ffi.C.free)
+ instance._CDATA = ffi.gc(ffi.cast("unsigned char*", ptr), ffi.C.xm_ffi_free)
instance._MANAGED = true
else
instance._CDATA = ffi.cast("unsigned char*", ptr)
instance._MANAGED = false
end
else
- -- new(size): allocates a buffer of given size
- ptr = ffi.C.malloc(size)
- instance._CDATA = ffi.gc(ffi.cast("unsigned char*", ptr), ffi.C.free)
+ -- bytes(size): allocates a buffer of given size
+ ptr = ffi.C.xm_ffi_malloc(size)
+ instance._CDATA = ffi.gc(ffi.cast("unsigned char*", ptr), ffi.C.xm_ffi_free)
instance._MANAGED = true
end
instance._SIZE = size
elseif type(arg1) == "string" then
- -- new(str): allocates a buffer from the given string
+ -- bytes(str): mounts a buffer from the given string
local str = arg1
instance._SIZE = #str
instance._CDATA = ffi.cast("unsigned char*", str)
instance._REF = str -- keep ref for GC
instance._MANAGED = false
- else
+ elseif type(arg1) == "table" then
+ if type(arg2) == 'number' then
+ -- bytes(bytes, start, last): mounts a buffer from another one, with start/last limits:
+ local b = arg1
+ local start = arg2 or 1
+ local last = arg3 or b:size()
+ if start < 1 or last > b:size() then
+ os.raise("incorrect bounds(%d-%d) for bytes(...)!", start, last)
+ end
+ instance._SIZE = last - start + 1
+ instance._CDATA = b:cdata() - 1 + start
+ instance._REF = b -- keep lua ref for GC
+ instance._MANAGED = false
+ elseif type(arg2) == "table" then
+ -- bytes(bytes1, bytes2, bytes3, ...): allocates and concat buffer from list of byte buffers
+ instance._SIZE = 0
+ for _, b in ipairs(args) do
+ instance._SIZE = instance._SIZE + b:size()
+ end
+ instance._CDATA = ffi.gc(ffi.cast("unsigned char*", ffi.C.xm_ffi_malloc(instance._SIZE)), ffi.C.xm_ffi_free)
+ local offset = 0
+ for _, b in ipairs(args) do
+ ffi.copy(instance._CDATA + offset, b:cdata(), b:size())
+ offset = offset + b:size()
+ end
+ instance._MANAGED = true
+ elseif not arg2 and arg1:size() then
+ -- bytes(bytes): allocates a buffer from another one (strict replica, sharing memory)
+ local b = arg1
+ local start = 1
+ local last = arg3 or b:size()
+ if start < 1 or last > b:size() then
+ os.raise("incorrect bounds(%d-%d)!", start, last)
+ end
+ instance._SIZE = last - start + 1
+ instance._CDATA = b:cdata() - 1 + start
+ instance._REF = b -- keep lua ref for GC
+ instance._MANAGED = false
+ end
+ end
+ if instance:cdata() == nil then
os.raise("invalid arguments for bytes(...)!")
end
setmetatable(instance, _instance)
@@ -80,6 +125,11 @@ function _instance:size()
return self._SIZE
end
+-- get bytes data
+function _instance:cdata()
+ return self._CDATA
+end
+
-- bytes:ipairs()
function _instance:ipairs()
local index = 0
@@ -91,23 +141,59 @@ function _instance:ipairs()
end
end
--- bytes[key]
+-- get a slice of bytes
+function _instance:slice(start, last)
+ return bytes(self, start, last)
+end
+
+-- copy bytes
+function _instance:copy(src)
+ if type(src) == 'string' then
+ src = bytes(src)
+ end
+ if src:size() ~= self:size() then
+ os.raise("cannot copy bytes, src and dst must have same size(%d->%d)!", src:size(), self:size())
+ end
+ ffi.copy(self:cdata(), src:cdata(), self:size())
+ return self
+end
+
+-- clone a new bytes buffer
+function _instance:clone()
+ local new = bytes(self:size())
+ new:copy(self)
+ return new
+end
+
+-- convert bytes to string
+function _instance:str(i, j)
+ local offset = i and i - 1 or 0
+ return ffi.string(self:cdata() + offset, (j or self:size()) - offset)
+end
+
+-- get byte or bytes slice at the given index position
+--
+-- bytes[1]
+-- bytes[{1, 2}]
+--
function _instance:__index(key)
if type(key) == "number" then
if key < 1 or key > self:size() then
os.raise("bytes index(%d/%d) out of bounds!", key, self:size())
end
return self._CDATA[key - 1]
- --[[
elseif type(key) == "table" then
local start, last = key[1], key[2]
return self:slice(start, last)
- --]]
end
return rawget(self, key)
end
--- bytes[key] = value
+-- get byte or bytes slice at the given index position
+--
+-- bytes[1] = 0x1
+-- bytes[{1, 2}] = bytes(2)
+--
function _instance:__newindex(key, value)
if type(key) == "number" then
if key < 1 or key > self:size() then
@@ -115,15 +201,22 @@ function _instance:__newindex(key, value)
end
self._CDATA[key - 1] = value
return
- --[[
elseif type(key) == "table" then
- local start,last = key[1],key[2]
+ local start, last = key[1], key[2]
self:slice(start,last):copy(value)
- return]]
+ return
end
rawset(self, key, value)
end
+-- concat two bytes buffer
+function _instance:__concat(other)
+ local new = bytes(self:size() + other:size())
+ new:slice(1, self:size()):copy(self)
+ new:slice(self:size() + 1, new:size()):copy(other)
+ return new
+end
+
-- tostring(bytes)
function _instance:__tostring()
local parts = {}