Skip to content
Draft
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
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,8 @@ bindings/java/crnd/messages/
bindings/go/crnd.go
bindings/rust/src/protos/*.rs
bindings/rust/src/bindings.rs
*.js
*.wasm
*.html
conaninfo.txt
conanmanifest.txt
19 changes: 15 additions & 4 deletions bindings/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
cmake_minimum_required(VERSION 3.8.0)

add_subdirectory(cpp)
add_subdirectory(java)
add_subdirectory(go)
add_subdirectory(rust)
if(${BINDINGS_CPP})
add_subdirectory(cpp)
endif()

if(${BINDINGS_JAVA})
add_subdirectory(java)
endif()

if (${BINDINGS_GO})
add_subdirectory(go)
endif()

if (${BINDINGS_RUST})
add_subdirectory(rust)
endif()
17 changes: 13 additions & 4 deletions conanfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class CppInside(ConanFile):

settings = "os", "arch", "compiler", "build_type"
generators = "cmake"
options = {#"cpp": [True, False], # It is always generated
options = {"cpp": [True, False], # It is always generated
"csharp": [True, False],
"java": [True, False],
"js": [True, False],
Expand All @@ -19,7 +19,7 @@ class CppInside(ConanFile):
"ruby": [True, False],
"go": [True, False],
}
default_options = {#"cpp": True,
default_options = {"cpp": True,
"csharp": True,
"java": True,
"js": True,
Expand All @@ -37,7 +37,7 @@ def build_requirements(self):

def requirements(self):
self.requires("protobuf/3.6.1@bincrafters/stable")
self.requires("boost/1.70.0@conan/stable")
#self.requires("boost/1.70.0@conan/stable")
self.requires("spdlog/1.3.1@bincrafters/stable")

def source(self):
Expand All @@ -61,13 +61,22 @@ def source(self):
else:
binding_folder = os.path.join(self.source_folder, "bindings", it, "messages")
os.makedirs(binding_folder, exist_ok=True)
command += " --{}_out={}".format(it, binding_folder)

if it == 'js':
command += " --js_out=import_style=commonjs,binary:{}".format(binding_folder)
else:
command += " --{}_out={}".format(it, binding_folder)
command += " {}".format(" ".join(messages))
with tools.environment_append(env):
self.run(command)

def _cmake(self):
cmake = CMake(self)
for it in ["cpp", "csharp", "java", "js", "objc", "php", "python", "ruby", "go"]:
cmake.definitions["bindings_{}".format(it).upper()] = bool(getattr(self.options, it))
cmake.definitions["example_{}".format(it).upper()] = bool(getattr(self.options, it))

cmake.definitions["EMSCRIPTEN"] = bool(self.settings.os == "Emscripten")
cmake.configure()
return cmake

Expand Down
104 changes: 104 additions & 0 deletions emscripten/bin/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
<html>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script type="text/javascript" src="libcrnd.js"></script>
<script type="text/javascript" src="bundle.js"></script>

<script type="text/javascript">
console.info("CRND JS wrapper");


function help_callback(state, data, status) {
console.log("> js::help_callback")

var message = crnd.parse_help(data);
console.log("[js] message.getName: >" + message.getName() + "<");
console.log("[js] message.getDescription: >" + message.getDescription() + "<");
console.log("< js::help_callback")
}

function sample_callback(state, data, status) {
console.log("> js::sample_callback")
var message = crnd.parse_sample(data);
draw_histogram(message.getSamplesList(), "LOGNORMAL (3, 0.2)");
console.log("< js::sample_callback")
}

function functionExists(f) {
return f && typeof f === "function";
}

Module.onRuntimeInitialized = function() {
//console.info("Checking functions exist");
assert(functionExists(Module._help));
assert(functionExists(Module._sample));

// Call the help
/*
var pointer = addFunction(help_callback);
var help = Module.cwrap('help', 'void', ['pointer', 'pointer']);
help(null, pointer);
removeFunction(pointer);
*/

// Request sample (LOGNORMAL)
var model = new crnd.model_pb.Model();
model.setId(crnd.model_pb.Model.LOGNORMAL);
model.getParamsMap()["mean"] = 3;
model.getParamsMap()["stddev"] = 0.2;

var sample_request = new crnd.sample_request_pb.SampleRequest();
sample_request.setModel(model);
sample_request.setSeed(12345);
sample_request.setNSamples(100000);

var bytes = serialize_sample_request(sample_request);

var pointer = addFunction(sample_callback);
var sample = Module.cwrap('sample', 'void', ['pointer', 'string', 'pointer']);
console.log("> js::sample");
sample(null, bytes, pointer);
console.log("< js::sample");
removeFunction(pointer);
}

function draw_histogram(rolls, title) {
var nstars = 300;
var nclasses = 20;

var p = [].fill.call({ length: nclasses+1 }, 0);
var max = Math.max.apply(null, rolls);
var min = Math.min.apply(null, rolls);
var step = (max-min)/nclasses;

rolls.forEach(function (elem, index) {
idx = Math.round((elem-min)/step);
p[idx] += 1;
});

var h3 = $('<h3></h3>').text(title);
$("#histogram").append(h3);

var table = $('<table></table>')

console.log(title);
for (var i = 0; i < nclasses; i++) {
var axis_x = (min+i*step+step/2).toFixed(6).padStart(9, "0");
var npstars = Math.round(p[i]*nstars/rolls.length);

console.log(axis_x + ": " + "*".repeat(npstars));
table.append("<tr><td>" + axis_x + "</td><td>" + "*".repeat(npstars) + "</td></tr>");
}
$("#histogram").append(table);
}

</script>


<body>

<div id="histogram">

</div>

</body>
</html>
11 changes: 11 additions & 0 deletions emscripten/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
rm -fr _build
mkdir _build

pushd _build
conan install ../../conanfile.py -g virtualenv --profile ../profile --build=missing -o csharp=False -o java=False -o objc=False -o php=False -o python=False -o ruby=False -o go=False -o cpp=False
conan source ../../conanfile.py --install-folder=. --source-folder=../../
conan build ../../conanfile.py
conan package ../../conanfile.py --package-folder=../
popd

browserify main.js --standalone crnd -o bin/bundle.js
49 changes: 49 additions & 0 deletions emscripten/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@

var help_pb = require('/Users/jgsogo/dev/projects/cpp-inside/bindings/js/messages/help_pb.js');
var sample_pb = require('/Users/jgsogo/dev/projects/cpp-inside/bindings/js/messages/sample_pb.js');
var model_pb = require('/Users/jgsogo/dev/projects/cpp-inside/bindings/js/messages/model_pb.js');
var sample_request_pb = require('/Users/jgsogo/dev/projects/cpp-inside/bindings/js/messages/sample_request_pb.js');

parse_help = function (data) {
json = JSON.parse(UTF8ToString(data));
var message = new help_pb.Help();
message.setName(json["name"]);
message.setDescription(json["description"]);
message.setVersion(json["version"]);
return message;
}

parse_sample = function (data) {
json = JSON.parse(UTF8ToString(data));

var model = new model_pb.Model();
model.setId(json["model"]["id"]);
model.getParamsMap()["mean"] = json["model"]["mean"];
model.getParamsMap()["stddev"] = json["model"]["stddev"];

var message = new sample_pb.Sample();
message.setModel(model);
message.setSeed(json["seed"]);
message.setSamplesList(json["samples"]);

return message;
}

serialize_sample_request = function(sample_request) {
var model = sample_request.getModel();
var params = model.getParamsMap();
return JSON.stringify({
"model": {
"id": "LOGNORMAL",
"params": {
"mean": params["mean"],
"stddev": params["stddev"]
}
},
"seed": sample_request.getSeed(),
"nSamples": sample_request.getNSamples()
});
}


module.exports = {parse_help: parse_help, parse_sample: parse_sample, serialize_sample_request: serialize_sample_request, sample_request_pb: sample_request_pb, model_pb: model_pb};
12 changes: 12 additions & 0 deletions emscripten/profile
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
include(default)
[settings]
os=Emscripten
arch=wasm
compiler=clang
compiler.version=6.0
compiler.libcxx=libc++
[options]
[build_requires]
emsdk_installer/1.38.29@bincrafters/stable
[env]

3 changes: 3 additions & 0 deletions emscripten/run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@

source _build/activate.sh
emrun ./bin/index.html
24 changes: 19 additions & 5 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,20 @@

add_subdirectory(cpp)
add_subdirectory(python)
add_subdirectory(java)
add_subdirectory(go)
add_subdirectory(rust)
if (${EXAMPLE_CPP})
add_subdirectory(cpp)
endif()

if (${EXAMPLE_PYTHON})
add_subdirectory(python)
endif()

if (${EXAMPLE_JAVA})
add_subdirectory(java)
endif()

if (${EXAMPLE_GO})
add_subdirectory(go)
endif()

if (${EXAMPLE_RUST})
add_subdirectory(rust)
endif()
28 changes: 27 additions & 1 deletion library/crnd/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,30 @@ target_compile_definitions(crnd PRIVATE SPDLOG_ACTIVE_LEVEL=0)
#define SPDLOG_LEVEL_WARN 3
#define SPDLOG_LEVEL_ERROR 4
#define SPDLOG_LEVEL_CRITICAL 5
#define SPDLOG_LEVEL_OFF 6
#define SPDLOG_LEVEL_OFF 6

if (${EMSCRIPTEN})
message("CMAKE_C_COMPILER: ${CMAKE_C_COMPILER}")
message("CMAKE_CPP_COMPILER: ${CMAKE_CPP_COMPILER}")

set(EXPORTED_FUNCTIONS
_help
_sample
)

# process exported functions
set(EXPORTED_FUNCTIONS_STR "")
list(JOIN EXPORTED_FUNCTIONS "," EXPORTED_FUNCTIONS_STR)

set(CMAKE_CXX_FLAGS "-s EXPORTED_FUNCTIONS=\"[${EXPORTED_FUNCTIONS_STR}]\" -s EXTRA_EXPORTED_RUNTIME_METHODS='[\"ccall\", \"cwrap\", \"addFunction\", \"removeFunction\", \"UTF8ToString\", \"stringToUTF8\"]' -s RESERVED_FUNCTION_POINTERS=10")

set_target_properties(crnd PROPERTIES
SUFFIX ".js"
LINK_FLAGS "--emrun")

install(FILES
${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/libcrnd.js
${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/libcrnd.wasm
DESTINATION bin)
endif()

2 changes: 1 addition & 1 deletion library/crnd/include/api_c.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ extern "C" {
typedef void (*callback_t)(void* state, const void* data, const void* status);

CRND_EXPORT void help(void* state, callback_t help_callback);
CRND_EXPORT void sample(void* state, const void* sample_request_in, callback_t sample_callback);
CRND_EXPORT void sample(void* state, char* sample_request_in, callback_t sample_callback);
#ifdef __cplusplus
}
#endif
Expand Down
25 changes: 21 additions & 4 deletions library/crnd/src/api_c.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include "../include/api_cpp.h"
#include "serialization.h"
#include <google/protobuf/util/json_util.h>


extern "C" {
Expand All @@ -15,20 +16,36 @@ extern "C" {
auto status = help(help_message);

SPDLOG_TRACE("C::help::before callback");
help_callback(state, Serialized<crnd::Help>(help_message), Serialized<crnd::Status>(*status));
//help_callback(state, Serialized<crnd::Help>(help_message), Serialized<crnd::Status>(*status));
std::string data;
google::protobuf::util::MessageToJsonString(help_message, &data);

std::string status_str;
google::protobuf::util::MessageToJsonString(*status, &status_str);

help_callback(state, (void*)data.c_str(), (void*)status_str.c_str());
SPDLOG_TRACE("C::help::after callback");
SPDLOG_DEBUG("< C::help");
}

void sample(void* state, const void* sample_request_in, callback_t sample_callback) {
void sample(void* state, char* sample_request_in, callback_t sample_callback) {
SPDLOG_DEBUG("> C::sample");

crnd::SampleRequest request_message = Serialized<crnd::SampleRequest>::parse(sample_request_in);
std::string sp(sample_request_in);
crnd::SampleRequest request_message;
google::protobuf::util::JsonStringToMessage(sp, &request_message);

crnd::Sample sample_message;
auto status = sample(request_message, sample_message);

SPDLOG_TRACE("C::sample::before callback");
sample_callback(state, Serialized<crnd::Sample>(sample_message), Serialized<crnd::Status>(*status));
std::string data;
google::protobuf::util::MessageToJsonString(sample_message, &data);

std::string status_str;
google::protobuf::util::MessageToJsonString(*status, &status_str);

sample_callback(state, (void*)data.c_str(), (void*)status_str.c_str());
SPDLOG_TRACE("C::sample::after callback");

SPDLOG_DEBUG("< C::sample");
Expand Down