commit 160eb791f7217e5626d080405efd2cca1f35ebf7
parent b234b7ed655db9c220bbf3fb2aa3ee60bfde4c31
Author: Joris Vink <joris@coders.se>
Date: Thu, 2 Apr 2015 13:20:01 +0200
Merge pull request #37 from Geenz/master
Allow modules to use C++.
Diffstat:
13 files changed, 241 insertions(+), 16 deletions(-)
diff --git a/examples/cpp/.gitignore b/examples/cpp/.gitignore
@@ -0,0 +1,5 @@
+*.o
+.objs
+cpp.so
+assets.h
+cert
diff --git a/examples/cpp/README.md b/examples/cpp/README.md
@@ -0,0 +1,30 @@
+Kore example showing how to use C++ support!
+
+All functions accessible to kore must have their prototypes wrapped with the extern keyword like so:
+```
+extern āCā {
+ int pageA(struct http_request *);
+ int pageB(struct http_request *);
+ int validatorA(struct http_request *, char *);
+}
+```
+
+You will also need to compile kore with the KORE_CPP_SUPPORT environment variable enabled:
+```
+ # env KORE_CPP_SUPPORT=1 make
+```
+
+In order to run this example with the default C++ settings (default compiler dialect, libstdc++):
+```
+ # kore run
+```
+
+In order to run with a specific dialect and C++ runtime:
+```
+ # env CXXSTD=c++11 CXXLIB=c++ kore run
+```
+
+You can also supply your own compiler combined with the above:
+```
+ # env CXX=clang++ CXXSTD=c++11 CXXLIB=c++ kore run
+```
diff --git a/examples/cpp/conf/cpp.conf b/examples/cpp/conf/cpp.conf
@@ -0,0 +1,11 @@
+# Placeholder configuration
+
+bind 127.0.0.1 8888
+load ./cpp.so
+ssl_dhparam dh2048.pem
+
+domain 127.0.0.1 {
+ certfile cert/server.crt
+ certkey cert/server.key
+ static / page
+}
diff --git a/examples/cpp/dh2048.pem b/examples/cpp/dh2048.pem
@@ -0,0 +1,8 @@
+-----BEGIN DH PARAMETERS-----
+MIIBCAKCAQEAn4f4Qn5SudFjEYPWTbUaOTLUH85YWmmPFW1+b5bRa9ygr+1wfamv
+VKVT7jO8c4msSNikUf6eEfoH0H4VTCaj+Habwu+Sj+I416r3mliMD4SjNsUJrBrY
+Y0QV3ZUgZz4A8ARk/WwQcRl8+ZXJz34IaLwAcpyNhoV46iHVxW0ty8ND0U4DIku/
+PNayKimu4BXWXk4RfwNVP59t8DQKqjshZ4fDnbotskmSZ+e+FHrd+Kvrq/WButvV
+Bzy9fYgnUlJ82g/bziCI83R2xAdtH014fR63MpElkqdNeChb94pPbEdFlNUvYIBN
+xx2vTUQMqRbB4UdG2zuzzr5j98HDdblQ+wIBAg==
+-----END DH PARAMETERS-----+
\ No newline at end of file
diff --git a/examples/cpp/src/cpp.cpp b/examples/cpp/src/cpp.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2015 Jonathan Goodman <geenz@geenzo.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <kore/kore.h>
+#include <kore/http.h>
+
+#include "example_class.h"
+
+extern "C" {
+ int page(struct http_request *);
+}
+
+int
+page(struct http_request *req)
+{
+ example_class example;
+ const char* str = example.a();
+ http_response(req, 200, static_cast<void*>(const_cast<char*>(str)), strlen(str));
+ return (KORE_RESULT_OK);
+}
diff --git a/examples/cpp/src/example_class.cpp b/examples/cpp/src/example_class.cpp
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2015 Jonathan Goodman <geenz@geenzo.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "example_class.h"
+
+example_class::example_class() {
+
+}
+
+example_class::~example_class() {
+
+}
+
+const char*
+example_class::a() {
+ return "Hello world!";
+}
diff --git a/examples/cpp/src/example_class.h b/examples/cpp/src/example_class.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2015 Jonathan Goodman <geenz@geenzo.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef ____example_class__
+#define ____example_class__
+
+#include <stdio.h>
+
+class example_class {
+
+public:
+ example_class();
+ ~example_class();
+
+ const char*
+ a();
+};
+
+#endif /* defined(____example_class__) */
diff --git a/includes/http.h b/includes/http.h
@@ -17,6 +17,10 @@
#ifndef __H_HTTP_H
#define __H_HTTP_H
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
#define HTTP_KEEPALIVE_TIME 20
#define HTTP_HSTS_ENABLE 31536000
#define HTTP_HEADER_MAX_LEN 4096
@@ -283,5 +287,7 @@ enum http_status_code {
HTTP_STATUS_GATEWAY_TIMEOUT = 504,
HTTP_STATUS_BAD_VERSION = 505
};
-
+#if defined(__cplusplus)
+}
+#endif
#endif /* !__H_HTTP_H */
diff --git a/includes/kore.h b/includes/kore.h
@@ -37,6 +37,10 @@
#include <unistd.h>
#include <zlib.h>
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
#if defined(__APPLE__)
#undef daemon
extern int daemon(int, int);
@@ -547,4 +551,8 @@ void spdy_stream_close(struct connection *,
struct spdy_header_block *spdy_header_block_create(int);
+#if defined(__cplusplus)
+}
+#endif
+
#endif /* !__H_KORE_H */
diff --git a/includes/pgsql.h b/includes/pgsql.h
@@ -22,6 +22,10 @@
#define KORE_PGSQL_FORMAT_TEXT 0
#define KORE_PGSQL_FORMAT_BINARY 1
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
struct pgsql_conn {
u_int8_t type;
u_int8_t flags;
@@ -58,6 +62,10 @@ void kore_pgsql_queue_remove(struct http_request *);
char *kore_pgsql_getvalue(struct kore_pgsql *, int, int);
int kore_pgsql_getlength(struct kore_pgsql *, int, int);
+#if defined(__cplusplus)
+}
+#endif
+
#define KORE_PGSQL_STATE_INIT 1
#define KORE_PGSQL_STATE_WAIT 2
#define KORE_PGSQL_STATE_RESULT 3
diff --git a/includes/spdy.h b/includes/spdy.h
@@ -20,6 +20,9 @@
#include <sys/types.h>
#include <sys/queue.h>
+#if defined(__cplusplus)
+extern "C" {
+#endif
struct spdy_ctrl_frame {
u_int16_t version;
u_int16_t type;
@@ -65,6 +68,10 @@ struct spdy_stream {
};
extern const unsigned char SPDY_dictionary_txt[];
+
+#if defined(__cplusplus)
+}
+#endif
#define KORE_SSL_PROTO_STRING "\x08spdy/3.1\x08http/1.1"
#define SPDY_CONTROL_FRAME(x) ((x & (1 << 31)))
diff --git a/includes/tasks.h b/includes/tasks.h
@@ -24,6 +24,10 @@
#define KORE_TASK_STATE_FINISHED 3
#define KORE_TASK_STATE_ABORT 4
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
struct http_request;
struct kore_task {
@@ -72,5 +76,9 @@ void kore_task_set_result(struct kore_task *, int);
int kore_task_state(struct kore_task *);
int kore_task_result(struct kore_task *);
+
+#if defined(__cplusplus)
+}
+#endif
#endif
diff --git a/src/cli.c b/src/cli.c
@@ -69,7 +69,8 @@ struct filegen {
struct cfile {
struct stat st;
- int build;
+ int build;
+ int cpp;
char *name;
char *fpath;
char *opath;
@@ -103,7 +104,7 @@ static int cli_file_requires_build(struct stat *, const char *);
static void cli_find_files(const char *,
void (*cb)(char *, struct dirent *));
static void cli_add_cfile(char *, char *, char *,
- struct stat *, int);
+ struct stat *, int, int);
static void cli_run(int, char **);
static void cli_help(int, char **);
@@ -189,6 +190,7 @@ static int s_fd = -1;
static char *appl = NULL;
static char *rootdir = NULL;
static char *compiler = "gcc";
+static char *cppcompiler = "g++";
static struct cfile_list source_files;
static int cfiles_count;
static struct cmd *command = NULL;
@@ -300,6 +302,9 @@ cli_build(int argc, char **argv)
if ((p = getenv("CC")) != NULL)
compiler = p;
+
+ if ((p = getenv("CXX")) != NULL)
+ cppcompiler = p;
cfiles_count = 0;
TAILQ_INIT(&source_files);
@@ -336,6 +341,7 @@ cli_build(int argc, char **argv)
/* Build all source files. */
cli_find_files(src_path, cli_register_cfile);
+
free(src_path);
requires_relink = 0;
@@ -603,8 +609,8 @@ cli_build_asset(char *fpath, struct dirent *dp)
*(ext)++ = '\0';
cli_write_asset(name, ext);
*ext = '_';
-
- cli_add_cfile(name, cpath, opath, &st, 0);
+
+ cli_add_cfile(name, cpath, opath, &st, 0, 0);
kore_mem_free(name);
return;
}
@@ -663,12 +669,12 @@ cli_build_asset(char *fpath, struct dirent *dp)
*--ext = '.';
/* Register the .c file now (cpath is free'd later). */
- cli_add_cfile(name, cpath, opath, &st, 1);
+ cli_add_cfile(name, cpath, opath, &st, 1, 0);
kore_mem_free(name);
}
static void
-cli_add_cfile(char *name, char *fpath, char *opath, struct stat *st, int build)
+cli_add_cfile(char *name, char *fpath, char *opath, struct stat *st, int build, int cpp)
{
struct cfile *cf;
@@ -677,6 +683,7 @@ cli_add_cfile(char *name, char *fpath, char *opath, struct stat *st, int build)
cf->st = *st;
cf->build = build;
+ cf->cpp = cpp;
cf->fpath = fpath;
cf->opath = opath;
cf->name = kore_strdup(name);
@@ -689,20 +696,26 @@ cli_register_cfile(char *fpath, struct dirent *dp)
{
struct stat st;
char *ext, *opath;
+ int cpp;
- if ((ext = strrchr(fpath, '.')) == NULL || strcmp(ext, ".c"))
+ if ((ext = strrchr(fpath, '.')) == NULL || !(!strcmp(ext, ".c") || !strcmp(ext, ".cpp")))
return;
+
+ if (!strcmp(ext, ".cpp"))
+ cpp = 1;
+ else
+ cpp = 0;
if (stat(fpath, &st) == -1)
cli_fatal("stat(%s): %s", fpath, errno_s);
(void)cli_vasprintf(&opath, "%s/.objs/%s.o", rootdir, dp->d_name);
if (!cli_file_requires_build(&st, opath)) {
- cli_add_cfile(dp->d_name, fpath, opath, &st, 0);
+ cli_add_cfile(dp->d_name, fpath, opath, &st, 0, cpp);
return;
}
-
- cli_add_cfile(dp->d_name, fpath, opath, &st, 1);
+
+ cli_add_cfile(dp->d_name, fpath, opath, &st, 1, cpp);
}
static void
@@ -847,7 +860,7 @@ cli_compile_cfile(void *arg)
{
int idx;
struct cfile *cf = arg;
- char *args[20], *ipath[2];
+ char *args[24], *ipath[2], *cppdialect;
#if defined(KORE_USE_PGSQL)
char *ppath;
#endif
@@ -885,13 +898,29 @@ cli_compile_cfile(void *arg)
args[idx++] = "-fPIC";
args[idx++] = "-g";
+ if (cf->cpp) {
+
+ args[idx++] = "-Woverloaded-virtual";
+ args[idx++] = "-Wold-style-cast";
+ args[idx++] = "-Wnon-virtual-dtor";
+
+ if ((cppdialect = getenv("CXXSTD")) != NULL) {
+ char *cppstandard = NULL;
+ (void)cli_vasprintf(&cppstandard, "-std=%s", cppdialect);
+ args[idx++] = cppstandard;
+ }
+ }
+
args[idx++] = "-c";
args[idx++] = cf->fpath;
args[idx++] = "-o";
args[idx++] = cf->opath;
args[idx] = NULL;
-
- execvp(compiler, args);
+
+ if (cf->cpp)
+ execvp(cppcompiler, args);
+ else
+ execvp(compiler, args);
}
static void
@@ -900,7 +929,8 @@ cli_link_library(void *arg)
struct cfile *cf;
int idx, f, i;
char *p, *libname, *flags[LD_FLAGS_MAX];
- char *args[cfiles_count + 10 + LD_FLAGS_MAX];
+ char *args[cfiles_count + 11 + LD_FLAGS_MAX];
+ char *cpplib;
if ((p = getenv("LDFLAGS")) != NULL)
f = kore_split_string(p, " ", flags, LD_FLAGS_MAX);
@@ -923,7 +953,15 @@ cli_link_library(void *arg)
TAILQ_FOREACH(cf, &source_files, list)
args[idx++] = cf->opath;
-
+
+ if ((cpplib = getenv("CXXLIB")) != NULL) {
+ char *cpplibrary = NULL;
+ (void)cli_vasprintf(&cpplibrary, "-l%s", cpplib);
+ args[idx++] = cpplibrary;
+ } else {
+ args[idx++] = "-lstdc++";
+ }
+
for (i = 0; i < f; i++)
args[idx++] = flags[i];