Skip to content

Commit

Permalink
Adds experimental FFI support.
Browse files Browse the repository at this point in the history
  • Loading branch information
silvioprog committed Oct 3, 2018
1 parent ae1fea0 commit 1202df3
Show file tree
Hide file tree
Showing 11 changed files with 373 additions and 2 deletions.
8 changes: 8 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ endif ()

set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)

option(SG_FFI_SUPPORT "Enable FFI support" ON)
option(SG_HTTPS_SUPPORT "Enable HTTPS support" OFF)
option(SG_PATH_ROUTING "Enable path routing" ON)

Expand All @@ -77,6 +78,10 @@ include(SgFlags)
include(SgGNUSource)
include(SgVersion)
include(SgABIComplianceChecker)
if (SG_FFI_SUPPORT)
include(SgFFI)
add_definitions(-DSG_FFI_SUPPORT=1)
endif ()
if (SG_HTTPS_SUPPORT)
include(FindGnuTLS)
if (GNUTLS_FOUND)
Expand Down Expand Up @@ -111,6 +116,9 @@ if (UNIX AND ((NOT APPLE) AND (NOT ANDROID)))
endif ()

include_directories(${SG_INCLUDE_DIR})
if (SG_FFI_SUPPORT)
include_directories(${FFI_INCLUDE_DIR})
endif ()
include_directories(${MHD_INCLUDE_DIR})
if (SG_PATH_ROUTING)
include_directories(${PCRE2_INCLUDE_DIR})
Expand Down
3 changes: 3 additions & 0 deletions cmake/SgDoxygen.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ if (SG_BUILD_HTML)
# set(SG_GENERATE_MAN_PAGES YES)
# set(DOXYGEN_MAN_DIR ${DOXYGEN_DOCS_DIR}/man)
#endif ()
if (SG_FFI_SUPPORT)
set(SG_FFI_SUPPORT_DOC "SG_FFI_SUPPORT")
endif ()
if (SG_HTTPS_SUPPORT AND GNUTLS_FOUND)
set(SG_HTTPS_SUPPORT_DOC "SG_HTTPS_SUPPORT")
endif ()
Expand Down
75 changes: 75 additions & 0 deletions cmake/SgFFI.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#.rst:
# SgFFI
# -----
#
# Build libffi.
#
# Build libffi from Sagui building.
#
# ::
#
# FFI_INCLUDE_DIR - Directory of includes.
# FFI_ARCHIVE_LIB - AR archive library.
#

# _
# ___ __ _ __ _ _ _(_)
# / __|/ _` |/ _` | | | | |
# \__ \ (_| | (_| | |_| | |
# |___/\__,_|\__, |\__,_|_|
# |___/
#
# –– cross-platform library which helps to develop web servers or frameworks.
#
# Copyright (c) 2016-2018 Silvio Clecio <[email protected]>
#
# This file is part of Sagui library.
#
# Sagui library is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Sagui library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Sagui library. If not, see <http:https://www.gnu.org/licenses/>.
#

if (__SG_FFI_INCLUDED)
return()
endif ()
set(__SG_FFI_INCLUDED ON)

set(FFI_NAME "libffi")
set(FFI_VER "3.2.1")
set(FFI_FULL_NAME "${FFI_NAME}-${FFI_VER}")
set(FFI_URL "ftp:https://sourceware.org/pub/libffi/${FFI_FULL_NAME}.tar.gz")
set(FFI_SHA256 "d06ebb8e1d9a22d19e38d63fdb83954253f39bedc5d46232a05645685722ca37")
set(FFI_OPTIONS
--enable-static=yes
--enable-shared=no)

ExternalProject_Add(${FFI_FULL_NAME}
URL ${FFI_URL} ${FFI_URL_MIRROR}
URL_HASH SHA256=${FFI_SHA256}
TIMEOUT 15
DOWNLOAD_DIR ${CMAKE_SOURCE_DIR}/lib
PREFIX ${CMAKE_BINARY_DIR}/${FFI_FULL_NAME}
SOURCE_DIR ${CMAKE_SOURCE_DIR}/lib/${FFI_FULL_NAME}
CONFIGURE_COMMAND <SOURCE_DIR>/configure --host=${CMAKE_C_MACHINE} --prefix=<INSTALL_DIR> ${FFI_OPTIONS}
BUILD_COMMAND ${CMAKE_MAKE_PROGRAM}
BINARY_DIR ${CMAKE_BINARY_DIR}/${FFI_FULL_NAME}
INSTALL_COMMAND ${CMAKE_MAKE_PROGRAM} install
LOG_DOWNLOAD ON
LOG_CONFIGURE ON
LOG_BUILD ON
LOG_INSTALL ON)

ExternalProject_Get_Property(${FFI_FULL_NAME} INSTALL_DIR)
set(FFI_INCLUDE_DIR ${INSTALL_DIR}/include)
set(FFI_ARCHIVE_LIB ${INSTALL_DIR}/lib/${FFI_NAME}.a)
unset(INSTALL_DIR)
9 changes: 9 additions & 0 deletions cmake/SgSummary.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,12 @@ if (${_build_type} MATCHES "[Rr]elease|RELEASE")
set(_is_release ON)
endif ()

if (SG_FFI_SUPPORT)
set(_ffi "Yes")
else ()
set(_ffi "No")
endif ()

if (SG_HTTPS_SUPPORT)
if (GNUTLS_FOUND)
set(_https_support "Yes")
Expand Down Expand Up @@ -175,6 +181,7 @@ endif ()
# Machine: ${CMAKE_C_MACHINE}
# CFLAGS: ${_cflags}
# Build: ${_build_type}-${_build_arch} (${_lib_type})
# FFI: ${_ffi}
# HTTPS: ${_https_support}
# Routing: ${_routing}
# Examples: ${_build_examples}
Expand All @@ -197,6 +204,7 @@ Sagui library ${VERSION} - building summary:
Machine: ${CMAKE_C_MACHINE}
CFLAGS: ${_cflags}
Build: ${_build_type}-${_build_arch} (${_lib_type})
FFI: ${_ffi}
HTTPS: ${_https_support}
Routing: ${_routing}
Examples: ${_build_examples}
Expand All @@ -212,6 +220,7 @@ unset(_cflags)
unset(_build_type)
unset(_build_arch)
unset(_lib_type)
unset(_ffi)
unset(_https_support)
unset(_build_examples)
unset(_build_html)
Expand Down
6 changes: 4 additions & 2 deletions doxygen/Doxyfile.in
Original file line number Diff line number Diff line change
Expand Up @@ -684,7 +684,8 @@ GENERATE_DEPRECATEDLIST= YES
# sections, marked by \if <section_label> ... \endif and \cond <section_label>
# ... \endcond blocks.

ENABLED_SECTIONS = @SG_HTTPS_SUPPORT_DOC@ \
ENABLED_SECTIONS = @SG_FFI_SUPPORT_DOC@ \
@SG_HTTPS_SUPPORT_DOC@ \
@SG_PATH_ROUTING_DOC@

# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
Expand Down Expand Up @@ -2090,7 +2091,8 @@ INCLUDE_FILE_PATTERNS =
# recursively expanded use the := operator instead of the = operator.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.

PREDEFINED = @SG_HTTPS_SUPPORT_DOC@ \
PREDEFINED = @SG_FFI_SUPPORT_DOC@ \
@SG_HTTPS_SUPPORT_DOC@ \
@SG_PATH_ROUTING_DOC@

# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
Expand Down
3 changes: 3 additions & 0 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ if (SG_BUILD_EXAMPLES)
httpsrv
httpuplds
httpsrv_benchmark)
if (SG_FFI_SUPPORT)
list(APPEND SG_EXAMPLES ffi)
endif ()
if (SG_HTTPS_SUPPORT AND GNUTLS_FOUND)
set(SG_EXAMPLES_CERTS_DIR "${SG_EXAMPLES_SOURCE_DIR}/certs")
add_definitions(-DSG_EXAMPLES_CERTS_DIR="${SG_EXAMPLES_CERTS_DIR}")
Expand Down
70 changes: 70 additions & 0 deletions examples/example_ffi.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/* _
* ___ __ _ __ _ _ _(_)
* / __|/ _` |/ _` | | | | |
* \__ \ (_| | (_| | |_| | |
* |___/\__,_|\__, |\__,_|_|
* |___/
*
* –– cross-platform library which helps to develop web servers or frameworks.
*
* Copyright (c) 2016-2018 Silvio Clecio <[email protected]>
*
* This file is part of Sagui library.
*
* Sagui library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Sagui library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Sagui library. If not, see <http:https://www.gnu.org/licenses/>.
*/

#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <sagui.h>

/* NOTE: Error checking has been omitted to make it clear. */

static char *my_function(bool b, int i, const char *s) {
const char *fmt = "%s|%d|%s";
const char *tf = (b ? "TRUE" : "FALSE");
char *str;
size_t len = (size_t) snprintf(NULL, 0, fmt, tf, i, s) + 1;
str = sg_alloc(len);
snprintf(str, len, fmt, tf, i, s);
return str;
}

int main(void) {
struct sg_ffi *ffi;
void *args[3];
char *ret = NULL;
bool b = true;
int i = 123;
const char *s = "abc";
args[0] = &b;
args[1] = &i;
args[2] = &s;
/* bis:s+p
* b = param 1: bool
* i = param 2: int
* p = param 3: pointer
* p = return: pointer
* d = default ABI
*/
//ffi = sg_ffi_new("bip:p:d");
ffi = sg_ffi_new("bip:p:d");
sg_ffi_call(ffi, (sg_ffi_fn) my_function, args, &ret);
printf("my_function: %s\n", ret);
sg_free(ret);
sg_ffi_free(ffi);
return EXIT_SUCCESS;
}
19 changes: 19 additions & 0 deletions include/sagui.h
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,25 @@ SG_EXTERN char *sg_tmpdir(void);

/** \} */

#ifdef SG_FFI_SUPPORT

/* experimental */
struct sg_ffi;

/* experimental */
typedef void (*sg_ffi_fn)(void);

/* experimental */
SG_EXTERN struct sg_ffi *sg_ffi_new(const char *opts);

/* experimental */
SG_EXTERN void sg_ffi_free(struct sg_ffi *ffi);

/* experimental */
SG_EXTERN int sg_ffi_call(struct sg_ffi *ffi, sg_ffi_fn fn, void **args, void *ret);

#endif

/**
* \ingroup sg_api
* \defgroup sg_str String
Expand Down
8 changes: 8 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ list(APPEND SG_C_SOURCE
${SG_SOURCE_DIR}/sg_httpreq.c
${SG_SOURCE_DIR}/sg_httpres.c
${SG_SOURCE_DIR}/sg_httpsrv.c)
if (SG_FFI_SUPPORT)
list(APPEND SG_C_SOURCE
${SG_SOURCE_DIR}/sg_ffi.c)
endif ()
if (SG_PATH_ROUTING)
list(APPEND SG_C_SOURCE
${SG_SOURCE_DIR}/sg_entrypoint.c
Expand Down Expand Up @@ -90,6 +94,10 @@ if (UNIX)
elseif (WIN32)
list(APPEND _libs ws2_32)
endif ()
if (SG_FFI_SUPPORT)
add_dependencies(sagui ${FFI_FULL_NAME})
list(APPEND _libs ${FFI_ARCHIVE_LIB})
endif ()
if (SG_HTTPS_SUPPORT AND GNUTLS_FOUND)
list(APPEND _libs ${GNUTLS_LIBRARIES})
endif ()
Expand Down
Loading

0 comments on commit 1202df3

Please sign in to comment.