mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
include/ruby/internal/core/rtypeddata.h: add doxygen
Must not be a bad idea to improve documents. [ci skip]
This commit is contained in:
parent
1561012918
commit
fdae26a5a8
Notes:
git
2021-09-10 20:01:44 +09:00
1 changed files with 422 additions and 4 deletions
|
@ -28,6 +28,8 @@
|
||||||
|
|
||||||
#include "ruby/internal/assume.h"
|
#include "ruby/internal/assume.h"
|
||||||
#include "ruby/internal/attr/artificial.h"
|
#include "ruby/internal/attr/artificial.h"
|
||||||
|
#include "ruby/internal/attr/flag_enum.h"
|
||||||
|
#include "ruby/internal/attr/nonnull.h"
|
||||||
#include "ruby/internal/attr/pure.h"
|
#include "ruby/internal/attr/pure.h"
|
||||||
#include "ruby/internal/cast.h"
|
#include "ruby/internal/cast.h"
|
||||||
#include "ruby/internal/core/rbasic.h"
|
#include "ruby/internal/core/rbasic.h"
|
||||||
|
@ -38,13 +40,68 @@
|
||||||
#include "ruby/internal/stdbool.h"
|
#include "ruby/internal/stdbool.h"
|
||||||
#include "ruby/internal/value_type.h"
|
#include "ruby/internal/value_type.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
*
|
||||||
|
* @deprecated This macro once was a thing in the old days, but makes no sense
|
||||||
|
* any longer today. Exists here for backwards compatibility
|
||||||
|
* only. You can safely forget about it.
|
||||||
|
*/
|
||||||
#define HAVE_TYPE_RB_DATA_TYPE_T 1
|
#define HAVE_TYPE_RB_DATA_TYPE_T 1
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
*
|
||||||
|
* @deprecated This macro once was a thing in the old days, but makes no sense
|
||||||
|
* any longer today. Exists here for backwards compatibility
|
||||||
|
* only. You can safely forget about it.
|
||||||
|
*/
|
||||||
#define HAVE_RB_DATA_TYPE_T_FUNCTION 1
|
#define HAVE_RB_DATA_TYPE_T_FUNCTION 1
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
*
|
||||||
|
* @deprecated This macro once was a thing in the old days, but makes no sense
|
||||||
|
* any longer today. Exists here for backwards compatibility
|
||||||
|
* only. You can safely forget about it.
|
||||||
|
*/
|
||||||
#define HAVE_RB_DATA_TYPE_T_PARENT 1
|
#define HAVE_RB_DATA_TYPE_T_PARENT 1
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a value you can set to ::rb_data_type_struct::dfree. Setting this
|
||||||
|
* means the data was allocated using ::ruby_xmalloc() (or variants), and shall
|
||||||
|
* be freed using ::ruby_xfree().
|
||||||
|
*
|
||||||
|
* @warning Do not use this if you want to use system malloc, because the
|
||||||
|
* system and Ruby might or might not share the same malloc
|
||||||
|
* implementation.
|
||||||
|
*/
|
||||||
#define RUBY_TYPED_DEFAULT_FREE RUBY_DEFAULT_FREE
|
#define RUBY_TYPED_DEFAULT_FREE RUBY_DEFAULT_FREE
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a value you can set to ::rb_data_type_struct::dfree. Setting this
|
||||||
|
* means the data is managed by someone else, like, statically allocated. Of
|
||||||
|
* course you are on your own then.
|
||||||
|
*/
|
||||||
#define RUBY_TYPED_NEVER_FREE RUBY_NEVER_FREE
|
#define RUBY_TYPED_NEVER_FREE RUBY_NEVER_FREE
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convenient casting macro.
|
||||||
|
*
|
||||||
|
* @param obj An object, which is in fact an ::RTypedData.
|
||||||
|
* @return The passed object casted to ::RTypedData.
|
||||||
|
*/
|
||||||
#define RTYPEDDATA(obj) RBIMPL_CAST((struct RTypedData *)(obj))
|
#define RTYPEDDATA(obj) RBIMPL_CAST((struct RTypedData *)(obj))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convenient getter macro.
|
||||||
|
*
|
||||||
|
* @param v An object, which is in fact an ::RTypedData.
|
||||||
|
* @return The passed object's ::RTypedData::data field.
|
||||||
|
*/
|
||||||
#define RTYPEDDATA_DATA(v) (RTYPEDDATA(v)->data)
|
#define RTYPEDDATA_DATA(v) (RTYPEDDATA(v)->data)
|
||||||
|
|
||||||
|
/** @old{rb_check_typeddata} */
|
||||||
#define Check_TypedStruct(v, t) \
|
#define Check_TypedStruct(v, t) \
|
||||||
rb_check_typeddata(RBIMPL_CAST((VALUE)(v)), (t))
|
rb_check_typeddata(RBIMPL_CAST((VALUE)(v)), (t))
|
||||||
|
|
||||||
|
@ -57,55 +114,365 @@
|
||||||
#define RUBY_TYPED_PROMOTED1 RUBY_TYPED_PROMOTED1
|
#define RUBY_TYPED_PROMOTED1 RUBY_TYPED_PROMOTED1
|
||||||
/** @endcond */
|
/** @endcond */
|
||||||
|
|
||||||
/* bits for rb_data_type_struct::flags */
|
/**
|
||||||
enum rbimpl_typeddata_flags {
|
* @private
|
||||||
|
*
|
||||||
|
* Bits for rb_data_type_struct::flags.
|
||||||
|
*/
|
||||||
|
enum
|
||||||
|
RBIMPL_ATTR_FLAG_ENUM()
|
||||||
|
rbimpl_typeddata_flags {
|
||||||
|
/**
|
||||||
|
* This flag has something to do with Ruby's global interpreter lock. For
|
||||||
|
* maximum safety, Ruby locks the entire VM during GC. However your
|
||||||
|
* callback functions could unintentionally unlock it, for instance when
|
||||||
|
* they try to flush an IO buffer. Such operations are dangerous (threads
|
||||||
|
* then run alongside of GC). By default, to prevent those scenario,
|
||||||
|
* callbacks are deferred until the GC engine is 100% sure threads can run.
|
||||||
|
* This flag skips that; structs with it are deallocated during the sweep
|
||||||
|
* phase.
|
||||||
|
*
|
||||||
|
* Using this flag needs deep understanding of both GC and threads. You
|
||||||
|
* would better leave it unspecified.
|
||||||
|
*/
|
||||||
RUBY_TYPED_FREE_IMMEDIATELY = 1,
|
RUBY_TYPED_FREE_IMMEDIATELY = 1,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This flag has something to do with Ractor. Multiple Ractors run without
|
||||||
|
* protecting each other. Sharing an object among Ractors is basically
|
||||||
|
* dangerous, disabled by default. This flag is used to bypass that
|
||||||
|
* restriction. but setting it is not enough. In addition to do so, an
|
||||||
|
* object also has to be frozen, and be passed to
|
||||||
|
* rb_ractor_make_shareable() before being actually shareable. Of course,
|
||||||
|
* you have to manually prevent race conditions then.
|
||||||
|
*
|
||||||
|
* Using this flag needs deep understanding of multithreaded programming.
|
||||||
|
* You would better leave it unspecified.
|
||||||
|
*/
|
||||||
RUBY_TYPED_FROZEN_SHAREABLE = RUBY_FL_SHAREABLE,
|
RUBY_TYPED_FROZEN_SHAREABLE = RUBY_FL_SHAREABLE,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This flag has something to do with our garbage collector. These days
|
||||||
|
* ruby objects are "generational". There are those who are young and
|
||||||
|
* those who are old. Young objects are prone to die; monitored relatively
|
||||||
|
* extensively by the garbage collector. OTOH old objects tend to live
|
||||||
|
* longer. They are relatively rarely considered. This basically works.
|
||||||
|
* But there is one tweak that has to be exercised. When an elder object
|
||||||
|
* has reference(s) to younger one(s), that referenced objects must not
|
||||||
|
* die. In order to detect additions of such references, old generations
|
||||||
|
* are protected by write barriers. It is a very difficult hack to
|
||||||
|
* appropriately insert write barriers everywhere. This mechanism is
|
||||||
|
* disabled by default for 3rd party extensions (they never get aged). By
|
||||||
|
* specifying this flag you can enable the generational feature to your
|
||||||
|
* data structure. Of course, you have to manually insert write barriers
|
||||||
|
* then.
|
||||||
|
*
|
||||||
|
* Using this flag needs deep understanding of GC internals, often at the
|
||||||
|
* level of source code. You would better leave it unspecified.
|
||||||
|
*/
|
||||||
RUBY_TYPED_WB_PROTECTED = RUBY_FL_WB_PROTECTED, /* THIS FLAG DEPENDS ON Ruby version */
|
RUBY_TYPED_WB_PROTECTED = RUBY_FL_WB_PROTECTED, /* THIS FLAG DEPENDS ON Ruby version */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This flag is mysterious. It seems nobody is currently using it. The
|
||||||
|
* intention of this flag is also unclear. We need further investigations.
|
||||||
|
*/
|
||||||
RUBY_TYPED_PROMOTED1 = RUBY_FL_PROMOTED1 /* THIS FLAG DEPENDS ON Ruby version */
|
RUBY_TYPED_PROMOTED1 = RUBY_FL_PROMOTED1 /* THIS FLAG DEPENDS ON Ruby version */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the struct that holds necessary info for a struct. It roughly
|
||||||
|
* resembles a Ruby level class; multiple objects can share a ::rb_data_type_t
|
||||||
|
* instance.
|
||||||
|
*/
|
||||||
typedef struct rb_data_type_struct rb_data_type_t;
|
typedef struct rb_data_type_struct rb_data_type_t;
|
||||||
|
|
||||||
|
/** @copydoc rb_data_type_t */
|
||||||
struct rb_data_type_struct {
|
struct rb_data_type_struct {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Name of structs of this kind. This is used for diagnostic purposes.
|
||||||
|
* This has to be unique in the process, but doesn't has to be a valid
|
||||||
|
* C/Ruby identifier.
|
||||||
|
*/
|
||||||
const char *wrap_struct_name;
|
const char *wrap_struct_name;
|
||||||
|
|
||||||
|
/** Function pointers. Resembles C++ `vtbl`.*/
|
||||||
struct {
|
struct {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function is called when the object is experiencing GC marks.
|
||||||
|
* If it contains references to other Ruby objects, you need to mark
|
||||||
|
* them also. Otherwise GC will smash your data.
|
||||||
|
*
|
||||||
|
* @see rb_gc_mark()
|
||||||
|
* @warning This is called during GC runs. Object allocations are
|
||||||
|
* impossible at that moment (that is why GC runs).
|
||||||
|
*/
|
||||||
RUBY_DATA_FUNC dmark;
|
RUBY_DATA_FUNC dmark;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function is called when the object is no longer used. You need
|
||||||
|
* to do whatever necessary to avoid memory leaks.
|
||||||
|
*
|
||||||
|
* @warning This is called during GC runs. Object allocations are
|
||||||
|
* impossible at that moment (that is why GC runs).
|
||||||
|
*/
|
||||||
RUBY_DATA_FUNC dfree;
|
RUBY_DATA_FUNC dfree;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function is to query the size of the underlying memory regions.
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
*
|
||||||
|
* This function has only one usage, which is form inside of
|
||||||
|
* `ext/objspace`.
|
||||||
|
*/
|
||||||
size_t (*dsize)(const void *);
|
size_t (*dsize)(const void *);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function is called when the object is relocated. Like
|
||||||
|
* ::rb_data_type_struct::dmark, you need to update references to Ruby
|
||||||
|
* objects inside of your structs.
|
||||||
|
*
|
||||||
|
* @see rb_gc_location()
|
||||||
|
* @warning This is called during GC runs. Object allocations are
|
||||||
|
* impossible at that moment (that is why GC runs).
|
||||||
|
*/
|
||||||
RUBY_DATA_FUNC dcompact;
|
RUBY_DATA_FUNC dcompact;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This field is reserved for future extension. For now, it must be
|
||||||
|
* filled with zeros.
|
||||||
|
*/
|
||||||
void *reserved[1]; /* For future extension.
|
void *reserved[1]; /* For future extension.
|
||||||
This array *must* be filled with ZERO. */
|
This array *must* be filled with ZERO. */
|
||||||
} function;
|
} function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parent of this class. Sometimes C structs have inheritance-like
|
||||||
|
* relationships. An example is `struct sockaddr` and its family. If you
|
||||||
|
* design such things, make ::rb_data_type_t for each of them and connect
|
||||||
|
* using this field. Ruby can then transparently cast your data back and
|
||||||
|
* forth when you call #TypedData_Get_Struct().
|
||||||
|
*
|
||||||
|
* ```CXX
|
||||||
|
* struct parent { };
|
||||||
|
* static inline const rb_data_type_t parent_type = {
|
||||||
|
* .wrap_struct_name = "parent",
|
||||||
|
* };
|
||||||
|
*
|
||||||
|
* struct child: public parent { };
|
||||||
|
* static inline const rb_data_type_t child_type = {
|
||||||
|
* .wrap_struct_name = "child",
|
||||||
|
* .parent = &parent_type,
|
||||||
|
* };
|
||||||
|
*
|
||||||
|
* // This function can take both parent_class and child_class.
|
||||||
|
* static inline struct parent *
|
||||||
|
* get_parent(VALUE v)
|
||||||
|
* {
|
||||||
|
* struct parent *p;
|
||||||
|
* TypedData_Get_Struct(v, parent_type, struct parent, p);
|
||||||
|
* return p;
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
const rb_data_type_t *parent;
|
const rb_data_type_t *parent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type-specific static data. This area can be used for any purpose by a
|
||||||
|
* programmer who define the type. Ruby does not manage this at all.
|
||||||
|
*/
|
||||||
void *data; /* This area can be used for any purpose
|
void *data; /* This area can be used for any purpose
|
||||||
by a programmer who define the type. */
|
by a programmer who define the type. */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type-specific behavioural characteristics. This is a bitfield. It is
|
||||||
|
* an EXTREMELY WISE IDEA to leave this field blank. It is designed so
|
||||||
|
* that setting zero is the safest thing to do. If you risk to set any
|
||||||
|
* bits on, you have to know exactly what you are doing.
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
*
|
||||||
|
* Why it has to be a ::VALUE? @shyouhei doesn't understand the design.
|
||||||
|
*/
|
||||||
VALUE flags; /* RUBY_FL_WB_PROTECTED */
|
VALUE flags; /* RUBY_FL_WB_PROTECTED */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* "Typed" user data. By using this, extension libraries can wrap a C struct
|
||||||
|
* to make it visible from Ruby. For instance if you have a `struct timeval`,
|
||||||
|
* and you want users to use it,
|
||||||
|
*
|
||||||
|
* ```CXX
|
||||||
|
* static inline const rb_data_type_t timeval_type = {
|
||||||
|
* // Note that unspecified fields are 0-filled by default.
|
||||||
|
* .wrap_struct_name = "timeval",
|
||||||
|
* .function = {
|
||||||
|
* .dmark = nullptr, // no need to mark
|
||||||
|
* .dfree = RUBY_TYPED_DEFAULT_FREE, // use ruby_xfree()
|
||||||
|
* .dsize = [](auto) {
|
||||||
|
* return sizeof(struct timeval);
|
||||||
|
* },
|
||||||
|
* },
|
||||||
|
* };
|
||||||
|
*
|
||||||
|
* extern "C" void
|
||||||
|
* Init_timeval(void)
|
||||||
|
* {
|
||||||
|
* auto klass = rb_define_class("YourName", rb_cObject);
|
||||||
|
*
|
||||||
|
* rb_define_alloc_func(klass, [](auto klass) {
|
||||||
|
* struct timeval *t;
|
||||||
|
* auto ret = TypedData_Make_Struct(
|
||||||
|
* klass, struct timeval, &timeval_type, t);
|
||||||
|
*
|
||||||
|
* if (auto i = gettimeofday(t, nullptr); i == -1) {
|
||||||
|
* rb_sys_fail("gettimeofday(3)");
|
||||||
|
* }
|
||||||
|
* else {
|
||||||
|
* return ret;
|
||||||
|
* }
|
||||||
|
* });
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
struct RTypedData {
|
struct RTypedData {
|
||||||
|
|
||||||
|
/** The part that all ruby objects have in common. */
|
||||||
struct RBasic basic;
|
struct RBasic basic;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This field stores various information about how Ruby should handle a
|
||||||
|
* data. This roughly resembles a Ruby level class (apart from method
|
||||||
|
* definition etc.)
|
||||||
|
*/
|
||||||
const rb_data_type_t *type;
|
const rb_data_type_t *type;
|
||||||
VALUE typed_flag; /* 1 or not */
|
|
||||||
|
/**
|
||||||
|
* This has to be always 1.
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
*
|
||||||
|
* Why, then, this is not a const ::VALUE?
|
||||||
|
*/
|
||||||
|
VALUE typed_flag;
|
||||||
|
|
||||||
|
/** Pointer to the actual C level struct that you want to wrap. */
|
||||||
void *data;
|
void *data;
|
||||||
};
|
};
|
||||||
|
|
||||||
RBIMPL_SYMBOL_EXPORT_BEGIN()
|
RBIMPL_SYMBOL_EXPORT_BEGIN()
|
||||||
VALUE rb_data_typed_object_wrap(VALUE klass, void *datap, const rb_data_type_t *);
|
RBIMPL_ATTR_NONNULL((3))
|
||||||
|
/**
|
||||||
|
* This is the primitive way to wrap an existing C struct into ::RTypedData.
|
||||||
|
*
|
||||||
|
* @param[in] klass Ruby level class of the returning object.
|
||||||
|
* @param[in] datap Pointer to the target C struct.
|
||||||
|
* @param[in] type The characteristics of the passed data.
|
||||||
|
* @exception rb_eTypeError `klass` is not a class.
|
||||||
|
* @exception rb_eNoMemError Out of memory.
|
||||||
|
* @return An allocated object that wraps `datap`.
|
||||||
|
*/
|
||||||
|
VALUE rb_data_typed_object_wrap(VALUE klass, void *datap, const rb_data_type_t *type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Identical to rb_data_typed_object_wrap(), except it allocates a new data
|
||||||
|
* region internally instead of taking an existing one. The allocation is done
|
||||||
|
* using ruby_calloc(). Hence it makes no sense for `type->function.dfree` to
|
||||||
|
* be anything other than ::RUBY_TYPED_DEFAULT_FREE.
|
||||||
|
*
|
||||||
|
* @param[in] klass Ruby level class of the returning object.
|
||||||
|
* @param[in] size Requested size of memory to allocate.
|
||||||
|
* @param[in] type The characteristics of the passed data.
|
||||||
|
* @exception rb_eTypeError `klass` is not a class.
|
||||||
|
* @exception rb_eNoMemError Out of memory.
|
||||||
|
* @return An allocated object that wraps a new `size` byte region.
|
||||||
|
*/
|
||||||
VALUE rb_data_typed_object_zalloc(VALUE klass, size_t size, const rb_data_type_t *type);
|
VALUE rb_data_typed_object_zalloc(VALUE klass, size_t size, const rb_data_type_t *type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks for the domestic relationship between the two.
|
||||||
|
*
|
||||||
|
* @param[in] child A data type supposed to be a child of `parent`.
|
||||||
|
* @param[in] parent A data type supposed to be a parent of `child`.
|
||||||
|
* @retval true `child` is a descendent of `parent`.
|
||||||
|
* @retval false Otherwise.
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
*
|
||||||
|
* You can path NULL to both arguments, don't know what that means though.
|
||||||
|
*/
|
||||||
int rb_typeddata_inherited_p(const rb_data_type_t *child, const rb_data_type_t *parent);
|
int rb_typeddata_inherited_p(const rb_data_type_t *child, const rb_data_type_t *parent);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the given object is of given kind.
|
||||||
|
*
|
||||||
|
* @param[in] obj An instance of ::RTypedData.
|
||||||
|
* @param[in] data_type Expected data type of `obj`.
|
||||||
|
* @retval true `obj` is of `data_type`.
|
||||||
|
* @retval false Otherwise.
|
||||||
|
*/
|
||||||
int rb_typeddata_is_kind_of(VALUE obj, const rb_data_type_t *data_type);
|
int rb_typeddata_is_kind_of(VALUE obj, const rb_data_type_t *data_type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Identical to rb_typeddata_is_kind_of(), except it raises exceptions instead
|
||||||
|
* of returning false.
|
||||||
|
*
|
||||||
|
* @param[in] obj An instance of ::RTypedData.
|
||||||
|
* @param[in] data_type Expected data type of `obj`.
|
||||||
|
* @exception rb_eTypeError obj is not of `data_type`.
|
||||||
|
* @return Unwrapped C struct that `obj` holds.
|
||||||
|
* @post Upon successful return `obj`'s type is guaranteed `data_type`.
|
||||||
|
*/
|
||||||
void *rb_check_typeddata(VALUE obj, const rb_data_type_t *data_type);
|
void *rb_check_typeddata(VALUE obj, const rb_data_type_t *data_type);
|
||||||
RBIMPL_SYMBOL_EXPORT_END()
|
RBIMPL_SYMBOL_EXPORT_END()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts sval, a pointer to your struct, into a Ruby object.
|
||||||
|
*
|
||||||
|
* @param klass A ruby level class.
|
||||||
|
* @param data_type The type of `sval`.
|
||||||
|
* @param sval A pointer to your struct.
|
||||||
|
* @exception rb_eTypeError `klass` is not a class.
|
||||||
|
* @exception rb_eNoMemError Out of memory.
|
||||||
|
* @return A created Ruby object.
|
||||||
|
*/
|
||||||
#define TypedData_Wrap_Struct(klass,data_type,sval)\
|
#define TypedData_Wrap_Struct(klass,data_type,sval)\
|
||||||
rb_data_typed_object_wrap((klass),(sval),(data_type))
|
rb_data_typed_object_wrap((klass),(sval),(data_type))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
*
|
||||||
|
* This is an implementation detail of #TypedData_Make_Struct. People don't
|
||||||
|
* use it directly.
|
||||||
|
*
|
||||||
|
* @param result Variable name of created Ruby object.
|
||||||
|
* @param klass Ruby level class of the object.
|
||||||
|
* @param type Type name of the C struct.
|
||||||
|
* @param size Size of the C struct.
|
||||||
|
* @param data_type The data type describing `type`.
|
||||||
|
* @param sval Variable name of created C struct.
|
||||||
|
*/
|
||||||
#define TypedData_Make_Struct0(result, klass, type, size, data_type, sval) \
|
#define TypedData_Make_Struct0(result, klass, type, size, data_type, sval) \
|
||||||
VALUE result = rb_data_typed_object_zalloc(klass, size, data_type); \
|
VALUE result = rb_data_typed_object_zalloc(klass, size, data_type); \
|
||||||
(sval) = RBIMPL_CAST((type *)RTYPEDDATA_DATA(result)); \
|
(sval) = RBIMPL_CAST((type *)RTYPEDDATA_DATA(result)); \
|
||||||
RBIMPL_CAST(/*suppress unused variable warnings*/(void)(sval))
|
RBIMPL_CAST(/*suppress unused variable warnings*/(void)(sval))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Identical to #TypedData_Wrap_Struct, except it allocates a new data region
|
||||||
|
* internally instead of taking an existing one. The allocation is done using
|
||||||
|
* ruby_calloc(). Hence it makes no sense for `data_type->function.dfree` to
|
||||||
|
* be anything other than ::RUBY_TYPED_DEFAULT_FREE.
|
||||||
|
*
|
||||||
|
* @param klass Ruby level class of the object.
|
||||||
|
* @param type Type name of the C struct.
|
||||||
|
* @param data_type The data type describing `type`.
|
||||||
|
* @param sval Variable name of created C struct.
|
||||||
|
* @exception rb_eTypeError `klass` is not a class.
|
||||||
|
* @exception rb_eNoMemError Out of memory.
|
||||||
|
* @return A created Ruby object.
|
||||||
|
*/
|
||||||
#ifdef HAVE_STMT_AND_DECL_IN_EXPR
|
#ifdef HAVE_STMT_AND_DECL_IN_EXPR
|
||||||
#define TypedData_Make_Struct(klass, type, data_type, sval) \
|
#define TypedData_Make_Struct(klass, type, data_type, sval) \
|
||||||
RB_GNUC_EXTENSION({ \
|
RB_GNUC_EXTENSION({ \
|
||||||
|
@ -127,11 +494,32 @@ RBIMPL_SYMBOL_EXPORT_END()
|
||||||
sizeof(type))
|
sizeof(type))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtains a C struct from inside of a wrapper Ruby object.
|
||||||
|
*
|
||||||
|
* @param obj An instance of ::RTypedData.
|
||||||
|
* @param type Type name of the C struct.
|
||||||
|
* @param data_type The data type describing `type`.
|
||||||
|
* @param sval Variable name of obtained C struct.
|
||||||
|
* @exception rb_eTypeError `obj` is not a kind of `data_type`.
|
||||||
|
* @return Unwrapped C struct that `obj` holds.
|
||||||
|
*/
|
||||||
#define TypedData_Get_Struct(obj,type,data_type,sval) \
|
#define TypedData_Get_Struct(obj,type,data_type,sval) \
|
||||||
((sval) = RBIMPL_CAST((type *)rb_check_typeddata((obj), (data_type))))
|
((sval) = RBIMPL_CAST((type *)rb_check_typeddata((obj), (data_type))))
|
||||||
|
|
||||||
RBIMPL_ATTR_PURE()
|
RBIMPL_ATTR_PURE()
|
||||||
RBIMPL_ATTR_ARTIFICIAL()
|
RBIMPL_ATTR_ARTIFICIAL()
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
*
|
||||||
|
* This is an implementation detail of Check_Type(). People don't use it
|
||||||
|
* directly.
|
||||||
|
*
|
||||||
|
* @param[in] obj Object in question
|
||||||
|
* @retval true `obj` is an instance of ::RTypedData.
|
||||||
|
* @retval false `obj` is an instance of ::RData.
|
||||||
|
* @pre `obj` must be a Ruby object of ::RUBY_T_DATA.
|
||||||
|
*/
|
||||||
static inline bool
|
static inline bool
|
||||||
rbimpl_rtypeddata_p(VALUE obj)
|
rbimpl_rtypeddata_p(VALUE obj)
|
||||||
{
|
{
|
||||||
|
@ -140,6 +528,14 @@ rbimpl_rtypeddata_p(VALUE obj)
|
||||||
|
|
||||||
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
|
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
|
||||||
RBIMPL_ATTR_ARTIFICIAL()
|
RBIMPL_ATTR_ARTIFICIAL()
|
||||||
|
/**
|
||||||
|
* Checks whether the passed object is ::RTypedData or ::RData.
|
||||||
|
*
|
||||||
|
* @param[in] obj Object in question
|
||||||
|
* @retval true `obj` is an instance of ::RTypedData.
|
||||||
|
* @retval false `obj` is an instance of ::RData.
|
||||||
|
* @pre `obj` must be a Ruby object of ::RUBY_T_DATA.
|
||||||
|
*/
|
||||||
static inline bool
|
static inline bool
|
||||||
RTYPEDDATA_P(VALUE obj)
|
RTYPEDDATA_P(VALUE obj)
|
||||||
{
|
{
|
||||||
|
@ -156,6 +552,13 @@ RTYPEDDATA_P(VALUE obj)
|
||||||
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
|
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
|
||||||
RBIMPL_ATTR_ARTIFICIAL()
|
RBIMPL_ATTR_ARTIFICIAL()
|
||||||
/* :TODO: can this function be __attribute__((returns_nonnull)) or not? */
|
/* :TODO: can this function be __attribute__((returns_nonnull)) or not? */
|
||||||
|
/**
|
||||||
|
* Queries for the type of given object.
|
||||||
|
*
|
||||||
|
* @param[in] obj Object in question
|
||||||
|
* @return Data type struct that corresponds to `obj`.
|
||||||
|
* @pre `obj` must be an instance of ::RTypedData.
|
||||||
|
*/
|
||||||
static inline const struct rb_data_type_struct *
|
static inline const struct rb_data_type_struct *
|
||||||
RTYPEDDATA_TYPE(VALUE obj)
|
RTYPEDDATA_TYPE(VALUE obj)
|
||||||
{
|
{
|
||||||
|
@ -169,6 +572,20 @@ RTYPEDDATA_TYPE(VALUE obj)
|
||||||
return RTYPEDDATA(obj)->type;
|
return RTYPEDDATA(obj)->type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* While we don't stop you from using this function, it seems to be an
|
||||||
|
* implementation detail of #TypedData_Make_Struct, which is preferred over
|
||||||
|
* this one.
|
||||||
|
*
|
||||||
|
* @param[in] klass Ruby level class of the returning object.
|
||||||
|
* @param[in] type The data type
|
||||||
|
* @param[out] datap Return pointer.
|
||||||
|
* @param[in] size Size of the C struct.
|
||||||
|
* @exception rb_eTypeError `klass` is not a class.
|
||||||
|
* @exception rb_eNoMemError Out of memory.
|
||||||
|
* @return A created Ruby object.
|
||||||
|
* @post `*datap` points to the C struct wrapped by the returned object.
|
||||||
|
*/
|
||||||
static inline VALUE
|
static inline VALUE
|
||||||
rb_data_typed_object_make(VALUE klass, const rb_data_type_t *type, void **datap, size_t size)
|
rb_data_typed_object_make(VALUE klass, const rb_data_type_t *type, void **datap, size_t size)
|
||||||
{
|
{
|
||||||
|
@ -177,6 +594,7 @@ rb_data_typed_object_make(VALUE klass, const rb_data_type_t *type, void **datap,
|
||||||
}
|
}
|
||||||
|
|
||||||
RBIMPL_ATTR_DEPRECATED(("by: rb_data_typed_object_wrap"))
|
RBIMPL_ATTR_DEPRECATED(("by: rb_data_typed_object_wrap"))
|
||||||
|
/** @deprecated This function was renamed to rb_data_typed_object_wrap(). */
|
||||||
static inline VALUE
|
static inline VALUE
|
||||||
rb_data_typed_object_alloc(VALUE klass, void *datap, const rb_data_type_t *type)
|
rb_data_typed_object_alloc(VALUE klass, void *datap, const rb_data_type_t *type)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue