Skip to content
Open
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
14 changes: 13 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ include(CheckFunctionExists)
include(CheckSymbolExists)

PROJECT(ucode C)
ADD_DEFINITIONS(-Os -Wall -Werror --std=gnu99 -ffunction-sections -fwrapv -D_GNU_SOURCE)
ADD_DEFINITIONS(-Os -Wall -Werror --std=gnu11 -ffunction-sections -fwrapv -D_GNU_SOURCE)

IF(CMAKE_C_COMPILER_VERSION VERSION_GREATER 6)
ADD_DEFINITIONS(-Wextra -Werror=implicit-function-declaration)
Expand All @@ -27,6 +27,7 @@ OPTION(RTNL_SUPPORT "Route Netlink plugin support" ${LINUX})
OPTION(NL80211_SUPPORT "Wireless Netlink plugin support" ${LINUX})
OPTION(RESOLV_SUPPORT "NS resolve plugin support" ON)
OPTION(STRUCT_SUPPORT "Struct plugin support" ON)
OPTION(CTYPES_SUPPORT "Ctypes plugin support" ON)
OPTION(ULOOP_SUPPORT "Uloop plugin support" ON)

SET(LIB_SEARCH_PATH "${CMAKE_INSTALL_PREFIX}/lib/ucode/*.so:${CMAKE_INSTALL_PREFIX}/share/ucode/*.uc:./*.so:./*.uc" CACHE STRING "Default library search path")
Expand Down Expand Up @@ -192,6 +193,17 @@ IF(STRUCT_SUPPORT)
ENDIF()
ENDIF()

IF(CTYPES_SUPPORT)
FIND_LIBRARY(ffi NAMES ffi)
FIND_PATH(ffi_include_dir NAMES ffi.h)
INCLUDE_DIRECTORIES(${ffi_include_dir})
SET(LIBRARIES ${LIBRARIES} ctypes_lib)
ADD_LIBRARY(ctypes_lib MODULE lib/ctypes.c)
SET_TARGET_PROPERTIES(ctypes_lib PROPERTIES OUTPUT_NAME ctypes PREFIX "")
TARGET_LINK_OPTIONS(ctypes_lib PRIVATE ${UCODE_MODULE_LINK_OPTIONS})
TARGET_LINK_LIBRARIES(ctypes_lib ${ffi})
ENDIF()

IF(ULOOP_SUPPORT)
FIND_LIBRARY(ubox NAMES ubox)
FIND_PATH(uloop_include_dir NAMES libubox/uloop.h)
Expand Down
57 changes: 57 additions & 0 deletions examples/ctypes.uc
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
const c = require("ctypes");
const struct = require("struct");

const sizeof = (abbreviation) => length(struct.pack(abbreviation));

const abbreviation_to_ffi = {
i: c.ffi_type.sint,
P: c.ffi_type.pointer,
N: c.ffi_type["uint" + sizeof("N") * 8],
};

function attach(dl_handle, fun) {
const params_list = split(fun.params, "");
const cif = c.prep(
c.const.FFI_DEFAULT_ABI,
...map(params_list, (a) => abbreviation_to_ffi[a])
);
return function (...args) {
const packed = struct.pack(fun.params, 0, ...args);
const return_buffer = c.ptr(packed);
const s = c.symbol(dl_handle, fun.name);
assert(s != null);
assert(cif.call(s, return_buffer));
return struct.unpack(
substr(fun.params, 0, 1),
return_buffer.ucv_string_new()
)[0];
};
}

const libc = {};
for (fun in [
{ name: "dlopen", params: "PPi" },
{ name: "strlen", params: "NP" },
]) {
libc[fun.name] = attach(c.const.RTLD_DEFAULT, fun);
}

function dlopen(library_name) {
const library_name_copy = c.ptr(library_name);
const return_ptr = libc.dlopen(library_name_copy.as_int(), c.const.RTLD_NOW);
assert(library_name_copy.drop());
assert(return_ptr != 0);
return c.ptr(return_ptr);
}

const c_sqlite_version = attach(dlopen("libsqlite3.so.0"), {
name: "sqlite3_libversion",
params: "P",
});
function sqlite_version() {
const return_ptr = c_sqlite_version();
const len = libc.strlen(return_ptr);
return c.ptr(return_ptr).ucv_string_new(len);
}

print("sqlite version: ", sqlite_version(), "\n");
Loading