Skip to content

Commit

Permalink
Merge pull request #230 from ruby-rice/dev
Browse files Browse the repository at this point in the history
Various updates
  • Loading branch information
cfis authored Dec 7, 2024
2 parents 5d51039 + 8af2282 commit 5df7f0d
Show file tree
Hide file tree
Showing 23 changed files with 1,892 additions and 630 deletions.
414 changes: 226 additions & 188 deletions FindRuby.cmake

Large diffs are not rendered by default.

1,354 changes: 1,041 additions & 313 deletions include/rice/rice.hpp

Large diffs are not rendered by default.

398 changes: 277 additions & 121 deletions include/rice/stl.hpp

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions lib/rice.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
require "version"
5 changes: 5 additions & 0 deletions rice/Data_Object.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,11 @@ namespace Rice::detail
}
}

VALUE convert(const void* data)
{
return convert((void*)data);
}

private:
Return* returnInfo_ = nullptr;
};
Expand Down
12 changes: 8 additions & 4 deletions rice/Data_Type.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -156,12 +156,12 @@ namespace Rice
}

template<typename T>
template<typename Func_T>
Data_Type<T>& Data_Type<T>::define(Func_T func)
template<typename Function_T>
inline Data_Type<T>& Data_Type<T>::define(Function_T func)
{
// The passed in this pointer is an RValue, so we need to keep it alive by
// The passed in this pointer is an RValue, so we need to keep it alive by
// assigning it to a const lvalue
const Data_Type<T>& dummy = *this;
const auto& dummy = *this;
func(*this);
return *this;
}
Expand Down Expand Up @@ -220,6 +220,8 @@ namespace Rice
}
else
{
// This gives a chance for to auto-register classes such as std::exception
detail::verifyType<Base_T>();
superKlass = Data_Type<Base_T>::klass();
}

Expand All @@ -243,6 +245,8 @@ namespace Rice
}
else
{
// This gives a chance for to auto-register classes such as std::exception
detail::verifyType<Base_T>();
superKlass = Data_Type<Base_T>::klass();
}

Expand Down
5 changes: 4 additions & 1 deletion rice/Enum.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,10 @@ namespace Rice
};

template<typename T>
Enum<T> define_enum(char const* name, Module module = rb_cObject);
Enum<T> define_enum(char const* name);

template<typename T>
Enum<T> define_enum_under(char const* name, Module module );
} // namespace Rice

#include "Enum.ipp"
Expand Down
8 changes: 7 additions & 1 deletion rice/Enum.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,13 @@ namespace Rice
}

template<typename Enum_T>
Enum<Enum_T> define_enum(char const* name, Module module)
Enum<Enum_T> define_enum(char const* name)
{
return define_enum_under<Enum_T>(name, rb_cObject);
}

template<typename Enum_T>
Enum<Enum_T> define_enum_under(char const* name, Module module)
{
if (detail::Registries::instance.types.isDefined<Enum_T>())
{
Expand Down
8 changes: 8 additions & 0 deletions rice/cpp_api/Module.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,14 @@ namespace Rice
detail::NativeFunction<VALUE, Function_T, IsMethod>::define(klass, name, std::forward<Function_T>(function), methodInfo);
}

template<typename Constant_T>
inline Module& Module::define_constant(std::string name, Constant_T value)
{
using Base_T = detail::remove_cv_recursive_t<Constant_T>;
detail::protect(rb_define_const, this->value(), name.c_str(), detail::To_Ruby<Base_T>().convert(value));
return *this;
}

inline Module define_module_under(Object module, char const* name)
{
return detail::protect(rb_define_module_under, module.value(), name);
Expand Down
4 changes: 4 additions & 0 deletions rice/cpp_api/Module_defn.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ namespace Rice
*/
Object module_eval(String const& s);

//! Define a constant
template<typename Constant_T>
Module& define_constant(std::string name, Constant_T value);

#include "shared_methods.hpp"

protected:
Expand Down
6 changes: 6 additions & 0 deletions rice/detail/TypeRegistry.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@ namespace Rice::detail
void validateUnverifiedTypes();
// Clear unverified types. This is mostly for unit tests
void clearUnverifiedTypes();

public:
// If true an exception will be thrown for unvalidated types. If false then a messages
// will be sent to stderr
bool isStrict = true;

private:
std::optional<std::pair<VALUE, rb_data_type_t*>> lookup(const std::type_info& typeInfo);
void raiseUnverifiedType(const std::string& typeName);
Expand Down
10 changes: 9 additions & 1 deletion rice/detail/TypeRegistry.ipp
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#include <iostream>
#include <stdexcept>
#include <sstream>
#include <typeindex>
Expand Down Expand Up @@ -150,7 +151,14 @@ namespace Rice::detail
stream << " " << typeName(typeIndex) << "\n";
}

throw std::invalid_argument(stream.str());
if (this->isStrict)
{
throw std::invalid_argument(stream.str());
}
else
{
std::cerr << stream.str() << std::flush;
}
}

inline void TypeRegistry::clearUnverifiedTypes()
Expand Down
1 change: 1 addition & 0 deletions rice/detail/to_ruby.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ namespace Rice
public:
VALUE convert(void const*)
{
throw std::runtime_error("Converting from void pointer is not implemented");
return Qnil;
}
};
Expand Down
2 changes: 2 additions & 0 deletions rice/stl.hpp
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
#ifndef Rice__stl__hpp_
#define Rice__stl__hpp_

#include "stl/exception.hpp"
#include "stl/string.hpp"
#include "stl/string_view.hpp"
#include "stl/complex.hpp"
#include "stl/optional.hpp"
#include "stl/reference_wrapper.hpp"
#include "stl/smart_ptr.hpp"
#include "stl/monostate.hpp"
#include "stl/type_index.hpp"
#include "stl/variant.hpp"
#include "stl/pair.hpp"
#include "stl/map.hpp"
Expand Down
6 changes: 6 additions & 0 deletions rice/stl/exception.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#ifndef Rice__stl__exception__hpp_
#define Rice__stl__exception__hpp_

#include "exception.ipp"

#endif // Rice__stl__exception__hpp_
33 changes: 33 additions & 0 deletions rice/stl/exception.ipp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#include <exception>

// Libraries sometime inherit custom exception objects from std::exception,
// so define it for Ruby if necessary
namespace Rice
{
namespace stl
{
inline Data_Type<std::exception> define_stl_exception()
{
Module rb_mRice = define_module("Rice");
Module rb_mmap = define_module_under(rb_mRice, "Std");
Data_Type<std::exception> rb_cStlException = define_class_under<std::exception>(rb_mmap, "Exception");
rb_cStlException.
define_constructor(Constructor<std::exception>()).
define_method("what", &std::exception::what);
return rb_cStlException;
}
}
}

namespace Rice::detail
{
template<>
struct Type<std::exception>
{
static bool verify()
{
Rice::stl::define_stl_exception();
return true;
}
};
}
6 changes: 6 additions & 0 deletions rice/stl/type_index.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#ifndef Rice__stl__type_index__hpp_
#define Rice__stl__type_index__hpp_

#include "type_index.ipp"

#endif // Rice__stl__type_index__hpp_
50 changes: 50 additions & 0 deletions rice/stl/type_index.ipp
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#include <typeindex>

namespace Rice::detail
{
template<>
struct Type<std::type_index>
{
constexpr static bool verify()
{
return true;
}
};

template<>
class To_Ruby<std::type_index>
{
public:
VALUE convert(const std::type_index& _)
{
throw std::runtime_error("std::type_index support is not yet implemented");
return Qnil;
}
};

template<>
class To_Ruby<std::type_index&>
{
public:
static VALUE convert(const std::type_index& data, bool takeOwnership = false)
{
throw std::runtime_error("std::type_index support is not yet implemented");
return Qnil;
}
};

template<>
class From_Ruby<std::type_index&>
{
public:
Convertible is_convertible(VALUE value)
{
return Convertible::None;
}

std::type_index& convert(VALUE value)
{
throw std::runtime_error("std::type_index support is not yet implemented");
}
};
}
2 changes: 2 additions & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ add_executable (unittest
"test_Ownership.cpp"
"test_Overloads.cpp"
"test_Self.cpp"
"test_Stl_Exception.cpp"
"test_Stl_Map.cpp"
"test_Stl_Optional.cpp"
"test_Stl_Pair.cpp"
Expand All @@ -66,6 +67,7 @@ add_executable (unittest
"test_String.cpp"
"test_Struct.cpp"
"test_Symbol.cpp"
"test_Template.cpp"
"test_To_From_Ruby.cpp"
"test_Tracking.cpp")

Expand Down
2 changes: 1 addition & 1 deletion test/test_Enum.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ namespace
TESTCASE(nested_enums)
{
Data_Type<Inner> inner = define_class<Inner>("Inner");
define_enum<Inner::Props>("Props", inner)
define_enum_under<Inner::Props>("Props", inner)
.define_value("VALUE1", Inner::VALUE1)
.define_value("VALUE2", Inner::VALUE2)
.define_value("VALUE3", Inner::VALUE3);
Expand Down
15 changes: 15 additions & 0 deletions test/test_Module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -577,3 +577,18 @@ TESTCASE(rvalue_function)

ASSERT_EQUAL(Qtrue, result.value());
}

namespace {
namespace Constants {
#define MY_PI 314
}
}

TESTCASE(constants)
{
Module m = anonymous_module().
define_constant("MY_PI", MY_PI);

Object result = m.module_eval(R"(MY_PI)");
ASSERT_EQUAL(314, detail::From_Ruby<int>().convert(result.value()));
}
54 changes: 54 additions & 0 deletions test/test_Stl_Exception.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#include <complex>
#include <memory>

#include "unittest.hpp"
#include "embed_ruby.hpp"
#include <rice/rice.hpp>
#include <rice/stl.hpp>

using namespace Rice;

TESTSUITE(StlException);

SETUP(StlException)
{
embed_ruby();
}

TEARDOWN(StlException)
{
rb_gc_start();
}

namespace
{
class MyException: public std::exception
{
public:
std::string hello()
{
return "Hello";
}
};
}

TESTCASE(StlExceptionCreate)
{
Module m = define_module("Testing");
Class c = define_class<MyException, std::exception>("MyException").
define_constructor(Constructor<MyException>()).
define_method("hello", &MyException::hello);

Object exception = c.create();
Object result = exception.call("hello");
ASSERT_EQUAL("Hello", detail::From_Ruby<std::string>().convert(result.value()));

#ifdef _MSC_VER
std::string expected = "Uknown exception";
#else
std::string expected = "std::exception";
#endif

result = exception.call("what");
ASSERT_EQUAL(expected, detail::From_Ruby<std::string>().convert(result.value()));
}
Loading

0 comments on commit 5df7f0d

Please sign in to comment.