diff options
| author | ruki <[email protected]> | 2019-11-01 00:50:39 +0800 |
|---|---|---|
| committer | ruki <[email protected]> | 2019-10-31 23:03:54 +0800 |
| commit | 56178606d872629cb3553bf912a742c84cf244e4 (patch) | |
| tree | fd11ec3abab4cca7dc093f6d55b5c7c3ee40386f | |
| parent | 7d47837062fba756f66e7bea313cb59f9a026477 (diff) | |
export ffi/malloc for windows
| -rw-r--r-- | core/src/demo/xmake.lua | 5 | ||||
| -rw-r--r-- | core/src/xmake/ffi.c | 53 | ||||
| -rw-r--r-- | core/src/xmake/ffi.h | 46 | ||||
| -rw-r--r-- | core/src/xmake/machine.c | 4 | ||||
| -rw-r--r-- | core/src/xmake/makefile | 1 | ||||
| -rw-r--r-- | xmake/core/base/bytes.lua | 133 |
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 = {} |
