Prevent segfaults on orphaned subview objects.
This commit is contained in:
parent
aeba61a787
commit
7faf5d6fd6
|
@ -181,8 +181,9 @@ namespace php_arma
|
||||||
fci.retval = &retval;
|
fci.retval = &retval;
|
||||||
|
|
||||||
auto native = THIS_NATIVE;
|
auto native = THIS_NATIVE;
|
||||||
native->for_each([&fci, &fcc](auto&& val) {
|
auto parent = get_parent_zval<ChildT>(&EX(This));
|
||||||
ZVAL_OBJ(&fci.params[0], mapval_dense<T>::create(&val));
|
native->for_each([&fci, &fcc, parent](auto&& val) {
|
||||||
|
ZVAL_OBJ(&fci.params[0], mapval_dense<T>::create(parent, &val));
|
||||||
zend_call_function(&fci, &fcc);
|
zend_call_function(&fci, &fcc);
|
||||||
zval_ptr_dtor(&fci.params[0]);
|
zval_ptr_dtor(&fci.params[0]);
|
||||||
zval_ptr_dtor(fci.retval);
|
zval_ptr_dtor(fci.retval);
|
||||||
|
|
|
@ -10,11 +10,11 @@ namespace php_arma
|
||||||
{
|
{
|
||||||
template <typename T, const char *Name>
|
template <typename T, const char *Name>
|
||||||
zend_always_inline
|
zend_always_inline
|
||||||
void property_declare(zend_class_entry *ce)
|
void property_declare_scalar(zend_class_entry *ce)
|
||||||
{
|
{
|
||||||
zval property;
|
zval property;
|
||||||
zval_set_scalar(&property, static_cast<T>(0));
|
zval_set_scalar(&property, static_cast<T>(0));
|
||||||
zend_declare_property(ce, Name, str::get_len(Name), &property, ZEND_ACC_PUBLIC);
|
property_declare<Name, ZEND_ACC_PUBLIC>(ce, &property);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
@ -393,8 +393,9 @@ namespace php_arma
|
||||||
void complex<T>::ce_init(zend_class_entry *parent_ce)
|
void complex<T>::ce_init(zend_class_entry *parent_ce)
|
||||||
{
|
{
|
||||||
ce = class_register<php_name::val>(parent_ce, me);
|
ce = class_register<php_name::val>(parent_ce, me);
|
||||||
property_declare<T, real_property_name>(ce);
|
property_declare_scalar<T, real_property_name>(ce);
|
||||||
property_declare<T, imag_property_name>(ce);
|
property_declare_scalar<T, imag_property_name>(ce);
|
||||||
|
|
||||||
object_handlers_init(&handlers);
|
object_handlers_init(&handlers);
|
||||||
handlers.read_dimension = read_dimension;
|
handlers.read_dimension = read_dimension;
|
||||||
handlers.write_property = write_property;
|
handlers.write_property = write_property;
|
||||||
|
|
|
@ -14,8 +14,8 @@
|
||||||
|
|
||||||
namespace php_arma
|
namespace php_arma
|
||||||
{
|
{
|
||||||
template <typename T, typename T1>
|
template <typename T, typename ChildT>
|
||||||
PHP_ARMA_METHOD(dense_matrix, __invoke, T, T1)
|
PHP_ARMA_METHOD(dense_matrix, __invoke, T, ChildT)
|
||||||
{
|
{
|
||||||
zend_long i, j;
|
zend_long i, j;
|
||||||
ZEND_PARSE_PARAMETERS_START(1, 2)
|
ZEND_PARSE_PARAMETERS_START(1, 2)
|
||||||
|
@ -25,13 +25,14 @@ namespace php_arma
|
||||||
ZEND_PARSE_PARAMETERS_END();
|
ZEND_PARSE_PARAMETERS_END();
|
||||||
|
|
||||||
auto native = THIS_NATIVE;
|
auto native = THIS_NATIVE;
|
||||||
|
auto parent = get_parent_zval<ChildT>(&EX(This));
|
||||||
|
|
||||||
zend_object *zobj;
|
zend_object *zobj;
|
||||||
try {
|
try {
|
||||||
if (EX_NUM_ARGS() == 1) {
|
if (EX_NUM_ARGS() == 1) {
|
||||||
zobj = mapval_dense<T>::create(&native->operator()(i));
|
zobj = mapval_dense<T>::create(parent, &native->operator()(i));
|
||||||
} else {
|
} else {
|
||||||
zobj = mapval_dense<T>::create(&native->operator()(i, j));
|
zobj = mapval_dense<T>::create(parent, &native->operator()(i, j));
|
||||||
}
|
}
|
||||||
} catch (const std::logic_error& err) {
|
} catch (const std::logic_error& err) {
|
||||||
// Index out of bounds.
|
// Index out of bounds.
|
||||||
|
@ -42,8 +43,8 @@ namespace php_arma
|
||||||
RETVAL_OBJ(zobj);
|
RETVAL_OBJ(zobj);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename T1>
|
template <typename T, typename ChildT>
|
||||||
PHP_ARMA_METHOD(dense_matrix, at, T, T1)
|
PHP_ARMA_METHOD(dense_matrix, at, T, ChildT)
|
||||||
{
|
{
|
||||||
zend_long i, j;
|
zend_long i, j;
|
||||||
ZEND_PARSE_PARAMETERS_START(1, 2)
|
ZEND_PARSE_PARAMETERS_START(1, 2)
|
||||||
|
@ -53,12 +54,13 @@ namespace php_arma
|
||||||
ZEND_PARSE_PARAMETERS_END();
|
ZEND_PARSE_PARAMETERS_END();
|
||||||
|
|
||||||
auto native = THIS_NATIVE;
|
auto native = THIS_NATIVE;
|
||||||
|
auto parent = get_parent_zval<ChildT>(&EX(This));
|
||||||
|
|
||||||
zend_object *zobj;
|
zend_object *zobj;
|
||||||
if (EX_NUM_ARGS() == 1) {
|
if (EX_NUM_ARGS() == 1) {
|
||||||
zobj = mapval_dense<T>::create(&native->operator[](i));
|
zobj = mapval_dense<T>::create(parent, &native->operator[](i));
|
||||||
} else {
|
} else {
|
||||||
zobj = mapval_dense<T>::create(&native->at(i, j));
|
zobj = mapval_dense<T>::create(parent, &native->at(i, j));
|
||||||
}
|
}
|
||||||
RETVAL_OBJ(zobj);
|
RETVAL_OBJ(zobj);
|
||||||
}
|
}
|
||||||
|
@ -87,7 +89,8 @@ namespace php_arma
|
||||||
using ret_t = typename ChildT::subview_t;
|
using ret_t = typename ChildT::subview_t;
|
||||||
|
|
||||||
auto native = THIS_NATIVE;
|
auto native = THIS_NATIVE;
|
||||||
auto zobj = ret_t::create(std::move(native->cols(first_col, last_col)));
|
auto parent = get_parent_zval<ChildT>(&EX(This));
|
||||||
|
auto zobj = ret_t::create(parent, std::move(native->cols(first_col, last_col)));
|
||||||
RETVAL_OBJ(zobj);
|
RETVAL_OBJ(zobj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,7 +106,8 @@ namespace php_arma
|
||||||
using ret_t = typename ChildT::subview_t;
|
using ret_t = typename ChildT::subview_t;
|
||||||
|
|
||||||
auto native = THIS_NATIVE;
|
auto native = THIS_NATIVE;
|
||||||
auto zobj = ret_t::create(std::move(native->rows(first_row, last_row)));
|
auto parent = get_parent_zval<ChildT>(&EX(This));
|
||||||
|
auto zobj = ret_t::create(parent, std::move(native->rows(first_row, last_row)));
|
||||||
RETVAL_OBJ(zobj);
|
RETVAL_OBJ(zobj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,12 +125,13 @@ namespace php_arma
|
||||||
using ret_t = typename ChildT::subview_t;
|
using ret_t = typename ChildT::subview_t;
|
||||||
|
|
||||||
auto native = THIS_NATIVE;
|
auto native = THIS_NATIVE;
|
||||||
auto zobj = ret_t::create(std::move(native->submat(first_row, first_col, last_row, last_col)));
|
auto parent = get_parent_zval<ChildT>(&EX(This));
|
||||||
|
auto zobj = ret_t::create(parent, std::move(native->submat(first_row, first_col, last_row, last_col)));
|
||||||
RETVAL_OBJ(zobj);
|
RETVAL_OBJ(zobj);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename T1>
|
template <typename T, typename ChildT>
|
||||||
PHP_ARMA_METHOD(dense_matrix, diag, T, T1)
|
PHP_ARMA_METHOD(dense_matrix, diag, T, ChildT)
|
||||||
{
|
{
|
||||||
zend_long k = 0;
|
zend_long k = 0;
|
||||||
ZEND_PARSE_PARAMETERS_START(0, 1)
|
ZEND_PARSE_PARAMETERS_START(0, 1)
|
||||||
|
@ -135,10 +140,11 @@ namespace php_arma
|
||||||
ZEND_PARSE_PARAMETERS_END();
|
ZEND_PARSE_PARAMETERS_END();
|
||||||
|
|
||||||
auto native = THIS_NATIVE;
|
auto native = THIS_NATIVE;
|
||||||
|
auto parent = get_parent_zval<ChildT>(&EX(This));
|
||||||
|
|
||||||
zend_object *zobj;
|
zend_object *zobj;
|
||||||
try {
|
try {
|
||||||
zobj = diagview<T>::create(std::move(native->diag(k)));
|
zobj = diagview<T>::create(parent, std::move(native->diag(k)));
|
||||||
} catch (const std::logic_error& err) {
|
} catch (const std::logic_error& err) {
|
||||||
// requested diagonal out of bounds
|
// requested diagonal out of bounds
|
||||||
throw_exception(err.what());
|
throw_exception(err.what());
|
||||||
|
|
|
@ -175,7 +175,7 @@ namespace php_arma
|
||||||
using ret_t = typename ChildT::subview_t;
|
using ret_t = typename ChildT::subview_t;
|
||||||
|
|
||||||
auto native = THIS_NATIVE;
|
auto native = THIS_NATIVE;
|
||||||
auto zobj = ret_t::create(std::move(native->head_cols(n_cols)));
|
auto zobj = ret_t::create(&EX(This), std::move(native->head_cols(n_cols)));
|
||||||
RETVAL_OBJ(zobj);
|
RETVAL_OBJ(zobj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -190,7 +190,7 @@ namespace php_arma
|
||||||
using ret_t = typename ChildT::subview_t;
|
using ret_t = typename ChildT::subview_t;
|
||||||
|
|
||||||
auto native = THIS_NATIVE;
|
auto native = THIS_NATIVE;
|
||||||
auto zobj = ret_t::create(std::move(native->head_rows(n_rows)));
|
auto zobj = ret_t::create(&EX(This), std::move(native->head_rows(n_rows)));
|
||||||
RETVAL_OBJ(zobj);
|
RETVAL_OBJ(zobj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,7 +205,7 @@ namespace php_arma
|
||||||
using ret_t = typename ChildT::subview_t;
|
using ret_t = typename ChildT::subview_t;
|
||||||
|
|
||||||
auto native = THIS_NATIVE;
|
auto native = THIS_NATIVE;
|
||||||
auto zobj = ret_t::create(std::move(native->tail_cols(n_cols)));
|
auto zobj = ret_t::create(&EX(This), std::move(native->tail_cols(n_cols)));
|
||||||
RETVAL_OBJ(zobj);
|
RETVAL_OBJ(zobj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -220,7 +220,7 @@ namespace php_arma
|
||||||
using ret_t = typename ChildT::subview_t;
|
using ret_t = typename ChildT::subview_t;
|
||||||
|
|
||||||
auto native = THIS_NATIVE;
|
auto native = THIS_NATIVE;
|
||||||
auto zobj = ret_t::create(std::move(native->tail_rows(n_rows)));
|
auto zobj = ret_t::create(&EX(This), std::move(native->tail_rows(n_rows)));
|
||||||
RETVAL_OBJ(zobj);
|
RETVAL_OBJ(zobj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,7 @@ namespace php_arma
|
||||||
PHP_ARMA_FENTRY(me)
|
PHP_ARMA_FENTRY(me)
|
||||||
));
|
));
|
||||||
ce->create_object = object_non_constructible;
|
ce->create_object = object_non_constructible;
|
||||||
|
declare_subview_parent(ce);
|
||||||
|
|
||||||
object_handlers_init(&handlers);
|
object_handlers_init(&handlers);
|
||||||
handlers.offset = sizeof(native_t);
|
handlers.offset = sizeof(native_t);
|
||||||
|
|
|
@ -8,16 +8,16 @@
|
||||||
#define PHP_ARMA_DIAGONAL_HH
|
#define PHP_ARMA_DIAGONAL_HH
|
||||||
|
|
||||||
#include "php_arma.hh"
|
#include "php_arma.hh"
|
||||||
|
#include "instantiable.hh"
|
||||||
#include "complex.hh"
|
#include "complex.hh"
|
||||||
#include "shared_methods.hh"
|
#include "shared_methods.hh"
|
||||||
|
|
||||||
namespace php_arma
|
namespace php_arma
|
||||||
{
|
{
|
||||||
template <typename T> struct mat;
|
template <typename T> struct mat;
|
||||||
template <typename T, typename T1> struct linear;
|
|
||||||
|
|
||||||
template <typename T, bool IsSparse>
|
template <typename T, bool IsSparse>
|
||||||
struct diagonal
|
struct diagonal : instantiable<diagonal<T, IsSparse>, true>
|
||||||
{
|
{
|
||||||
using native_t = std::conditional_t<IsSparse, arma::spdiagview<T>, arma::diagview<T>>;
|
using native_t = std::conditional_t<IsSparse, arma::spdiagview<T>, arma::diagview<T>>;
|
||||||
using orig_t = mat<T>;
|
using orig_t = mat<T>;
|
||||||
|
@ -26,13 +26,6 @@ namespace php_arma
|
||||||
|
|
||||||
friend void diagonal_init();
|
friend void diagonal_init();
|
||||||
|
|
||||||
template <typename... Ts>
|
|
||||||
zend_always_inline
|
|
||||||
static zend_object *create(Ts&&... args)
|
|
||||||
{
|
|
||||||
return object_create_ctor<native_t>(ce, &handlers, args...);
|
|
||||||
}
|
|
||||||
|
|
||||||
PHP_ARMA_CE_HANDLRES_DECLARE();
|
PHP_ARMA_CE_HANDLRES_DECLARE();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
//
|
||||||
|
// php-armadillo/instantiable.hh
|
||||||
|
//
|
||||||
|
// @Author CismonX
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef PHP_ARMA_INSTANTIABLE_HH
|
||||||
|
#define PHP_ARMA_INSTANTIABLE_HH
|
||||||
|
|
||||||
|
#include "php_arma.hh"
|
||||||
|
|
||||||
|
namespace php_arma
|
||||||
|
{
|
||||||
|
template <typename ChildT, bool IsSubview> struct instantiable;
|
||||||
|
|
||||||
|
template <typename ChildT>
|
||||||
|
struct instantiable<ChildT, false>
|
||||||
|
{
|
||||||
|
template <typename... Ts>
|
||||||
|
zend_always_inline
|
||||||
|
static zend_object *create(Ts&&... args)
|
||||||
|
{
|
||||||
|
return object_create_ctor<typename ChildT::native_t>(ChildT::ce, &ChildT::handlers, args...);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename ChildT>
|
||||||
|
struct instantiable<ChildT, true>
|
||||||
|
{
|
||||||
|
template <typename... Ts>
|
||||||
|
zend_always_inline
|
||||||
|
static zend_object *create(zval *parent, Ts&&... args)
|
||||||
|
{
|
||||||
|
auto zobj = object_create_ctor<typename ChildT::native_t>(ChildT::ce, &ChildT::handlers, args...);
|
||||||
|
object_set_property(zobj, 0, parent);
|
||||||
|
return zobj;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // !PHP_ARMA_INSTANTIABLE_HH
|
|
@ -44,6 +44,8 @@ namespace php_arma
|
||||||
{
|
{
|
||||||
ce = class_register<php_name::val>(parent_ce, me);
|
ce = class_register<php_name::val>(parent_ce, me);
|
||||||
ce->create_object = object_non_constructible;
|
ce->create_object = object_non_constructible;
|
||||||
|
declare_subview_parent(ce);
|
||||||
|
|
||||||
object_handlers_init(&handlers);
|
object_handlers_init(&handlers);
|
||||||
handlers.offset = sizeof(native_t);
|
handlers.offset = sizeof(native_t);
|
||||||
handlers.clone_obj = nullptr;
|
handlers.clone_obj = nullptr;
|
||||||
|
|
|
@ -56,19 +56,22 @@ namespace php_arma
|
||||||
}
|
}
|
||||||
|
|
||||||
zend_always_inline
|
zend_always_inline
|
||||||
static zend_object *create(native_t init_val)
|
static zend_object *create(zval *parent, native_t init_val)
|
||||||
{
|
{
|
||||||
|
zend_object *zobj;
|
||||||
if constexpr (IsSparse) {
|
if constexpr (IsSparse) {
|
||||||
return object_create<native_t>(ce, [&init_val](auto obj) {
|
zobj = object_create<native_t>(ce, [&init_val](auto obj) {
|
||||||
memcpy(obj, &init_val, sizeof(native_t));
|
memcpy(obj, &init_val, sizeof(native_t));
|
||||||
return &handlers;
|
return &handlers;
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
return object_create<native_t>(ce, [init_val](auto obj) {
|
zobj = object_create<native_t>(ce, [init_val](auto obj) {
|
||||||
*obj = init_val;
|
*obj = init_val;
|
||||||
return &handlers;
|
return &handlers;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
object_set_property(zobj, 0, parent);
|
||||||
|
return zobj;
|
||||||
}
|
}
|
||||||
|
|
||||||
PHP_ARMA_CE_HANDLRES_DECLARE();
|
PHP_ARMA_CE_HANDLRES_DECLARE();
|
||||||
|
|
10
src/mat.cc
10
src/mat.cc
|
@ -29,7 +29,7 @@ namespace php_arma
|
||||||
Z_PARAM_LONG(fill)
|
Z_PARAM_LONG(fill)
|
||||||
ZEND_PARSE_PARAMETERS_END();
|
ZEND_PARSE_PARAMETERS_END();
|
||||||
|
|
||||||
auto zobj = create(n_rows, n_cols);
|
auto zobj = mat::create(n_rows, n_cols);
|
||||||
fill::invoke(ZOBJ_NATIVE(zobj), fill);
|
fill::invoke(ZOBJ_NATIVE(zobj), fill);
|
||||||
RETVAL_OBJ(zobj);
|
RETVAL_OBJ(zobj);
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,7 @@ namespace php_arma
|
||||||
Z_PARAM_STR(text)
|
Z_PARAM_STR(text)
|
||||||
ZEND_PARSE_PARAMETERS_END();
|
ZEND_PARSE_PARAMETERS_END();
|
||||||
|
|
||||||
auto zobj = create(ZSTR_VAL(text));
|
auto zobj = mat::create(ZSTR_VAL(text));
|
||||||
RETVAL_OBJ(zobj);
|
RETVAL_OBJ(zobj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,7 +56,7 @@ namespace php_arma
|
||||||
|
|
||||||
auto num_rows = zend_hash_num_elements(Z_ARR_P(arr));
|
auto num_rows = zend_hash_num_elements(Z_ARR_P(arr));
|
||||||
if (UNEXPECTED(num_rows == 0)) {
|
if (UNEXPECTED(num_rows == 0)) {
|
||||||
RETURN_OBJ(create());
|
RETURN_OBJ(mat::create());
|
||||||
}
|
}
|
||||||
auto first_row = zend_hash_index_find(Z_ARR_P(arr), 0);
|
auto first_row = zend_hash_index_find(Z_ARR_P(arr), 0);
|
||||||
if (UNEXPECTED(first_row == nullptr || Z_TYPE_P(first_row) != IS_ARRAY)) {
|
if (UNEXPECTED(first_row == nullptr || Z_TYPE_P(first_row) != IS_ARRAY)) {
|
||||||
|
@ -65,10 +65,10 @@ namespace php_arma
|
||||||
}
|
}
|
||||||
auto num_cols = zend_hash_num_elements(Z_ARR_P(first_row));
|
auto num_cols = zend_hash_num_elements(Z_ARR_P(first_row));
|
||||||
if (UNEXPECTED(num_rows == 0)) {
|
if (UNEXPECTED(num_rows == 0)) {
|
||||||
RETURN_OBJ(create());
|
RETURN_OBJ(mat::create());
|
||||||
}
|
}
|
||||||
|
|
||||||
auto zobj = create(num_rows, num_cols);
|
auto zobj = mat::create(num_rows, num_cols);
|
||||||
auto native = ZOBJ_NATIVE(zobj);
|
auto native = ZOBJ_NATIVE(zobj);
|
||||||
size_t idx_row = 0;
|
size_t idx_row = 0;
|
||||||
size_t idx_col = 0;
|
size_t idx_col = 0;
|
||||||
|
|
10
src/mat.hh
10
src/mat.hh
|
@ -8,6 +8,7 @@
|
||||||
#define PHP_ARMA_MAT_HH
|
#define PHP_ARMA_MAT_HH
|
||||||
|
|
||||||
#include "php_arma.hh"
|
#include "php_arma.hh"
|
||||||
|
#include "instantiable.hh"
|
||||||
#include "complex.hh"
|
#include "complex.hh"
|
||||||
|
|
||||||
namespace php_arma
|
namespace php_arma
|
||||||
|
@ -15,7 +16,7 @@ namespace php_arma
|
||||||
template <typename T> struct subview_mat;
|
template <typename T> struct subview_mat;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct mat
|
struct mat : instantiable<mat<T>, false>
|
||||||
{
|
{
|
||||||
using native_t = arma::Mat<T>;
|
using native_t = arma::Mat<T>;
|
||||||
using orig_t = mat<T>;
|
using orig_t = mat<T>;
|
||||||
|
@ -25,13 +26,6 @@ namespace php_arma
|
||||||
|
|
||||||
friend void mat_init();
|
friend void mat_init();
|
||||||
|
|
||||||
template <typename... Ts>
|
|
||||||
zend_always_inline
|
|
||||||
static zend_object *create(Ts&&... args)
|
|
||||||
{
|
|
||||||
return object_create_ctor<native_t>(ce, &handlers, args...);
|
|
||||||
}
|
|
||||||
|
|
||||||
PHP_ARMA_CE_HANDLRES_DECLARE();
|
PHP_ARMA_CE_HANDLRES_DECLARE();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -180,6 +180,7 @@ namespace php_arma
|
||||||
|
|
||||||
constexpr const char namespace_prefix[] = "Arma\\";
|
constexpr const char namespace_prefix[] = "Arma\\";
|
||||||
constexpr const char internal_prefix[] = "Internal\\";
|
constexpr const char internal_prefix[] = "Internal\\";
|
||||||
|
constexpr const char empty[] = "";
|
||||||
|
|
||||||
template <const char *Str>
|
template <const char *Str>
|
||||||
constexpr auto with_arma_prefix
|
constexpr auto with_arma_prefix
|
||||||
|
@ -334,6 +335,19 @@ namespace php_arma
|
||||||
return ce;
|
return ce;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <const char *Name, int AccessType>
|
||||||
|
zend_always_inline
|
||||||
|
void property_declare(zend_class_entry *ce, zval *zv)
|
||||||
|
{
|
||||||
|
zend_declare_property(ce, Name, str::get_len(Name), zv, AccessType);
|
||||||
|
}
|
||||||
|
|
||||||
|
zend_always_inline
|
||||||
|
void declare_subview_parent(zend_class_entry *ce)
|
||||||
|
{
|
||||||
|
property_declare<str::empty, ZEND_ACC_PRIVATE>(ce, &EG(uninitialized_zval));
|
||||||
|
}
|
||||||
|
|
||||||
zend_always_inline
|
zend_always_inline
|
||||||
void object_handlers_init(zend_object_handlers *handlers)
|
void object_handlers_init(zend_object_handlers *handlers)
|
||||||
{
|
{
|
||||||
|
@ -354,6 +368,17 @@ namespace php_arma
|
||||||
return reinterpret_cast<T*>(zobj) - 1;
|
return reinterpret_cast<T*>(zobj) - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
zend_always_inline
|
||||||
|
zval *get_parent_zval(zval *current)
|
||||||
|
{
|
||||||
|
if constexpr (std::is_same_v<T, typename T::orig_t>) {
|
||||||
|
return current;
|
||||||
|
} else {
|
||||||
|
return OBJ_PROP_NUM(Z_OBJ_P(current), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Helper functions for function entry.
|
/// Helper functions for function entry.
|
||||||
|
|
||||||
zend_always_inline
|
zend_always_inline
|
||||||
|
@ -398,10 +423,12 @@ namespace php_arma
|
||||||
zend_always_inline
|
zend_always_inline
|
||||||
zend_object *object_create(zend_class_entry *ce, F&& init)
|
zend_object *object_create(zend_class_entry *ce, F&& init)
|
||||||
{
|
{
|
||||||
auto obj = reinterpret_cast<T*>(emalloc(sizeof(T) + sizeof(zend_object) - sizeof(zval)));
|
auto obj = reinterpret_cast<T*>(emalloc(sizeof(T) +
|
||||||
|
sizeof(zend_object) + zend_object_properties_size(ce)));
|
||||||
auto zobj = to_zend_object(obj);
|
auto zobj = to_zend_object(obj);
|
||||||
zobj->handlers = init(obj);
|
zobj->handlers = init(obj);
|
||||||
zend_object_std_init(zobj, ce);
|
zend_object_std_init(zobj, ce);
|
||||||
|
object_properties_init(zobj, ce);
|
||||||
return zobj;
|
return zobj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,10 +19,11 @@ namespace php_arma
|
||||||
ZEND_PARSE_PARAMETERS_END();
|
ZEND_PARSE_PARAMETERS_END();
|
||||||
|
|
||||||
auto native = THIS_NATIVE;
|
auto native = THIS_NATIVE;
|
||||||
|
auto parent = get_parent_zval<ChildT>(&EX(This));
|
||||||
|
|
||||||
zend_object *zobj;
|
zend_object *zobj;
|
||||||
try {
|
try {
|
||||||
zobj = mapval_dense<T>::create(&native->operator()(i));
|
zobj = mapval_dense<T>::create(parent, &native->operator()(i));
|
||||||
} catch (const std::logic_error& err) {
|
} catch (const std::logic_error& err) {
|
||||||
// Index out of bounds.
|
// Index out of bounds.
|
||||||
throw_exception(err.what());
|
throw_exception(err.what());
|
||||||
|
@ -41,8 +42,9 @@ namespace php_arma
|
||||||
ZEND_PARSE_PARAMETERS_END();
|
ZEND_PARSE_PARAMETERS_END();
|
||||||
|
|
||||||
auto native = THIS_NATIVE;
|
auto native = THIS_NATIVE;
|
||||||
|
auto parent = get_parent_zval<ChildT>(&EX(This));
|
||||||
|
|
||||||
auto zobj = mapval_dense<T>::create(&native->operator[](i));
|
auto zobj = mapval_dense<T>::create(parent, &native->operator[](i));
|
||||||
RETVAL_OBJ(zobj);
|
RETVAL_OBJ(zobj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,7 @@ namespace php_arma
|
||||||
PHP_ARMA_FENTRY(me)
|
PHP_ARMA_FENTRY(me)
|
||||||
));
|
));
|
||||||
ce->create_object = object_non_constructible;
|
ce->create_object = object_non_constructible;
|
||||||
|
declare_subview_parent(ce);
|
||||||
|
|
||||||
object_handlers_init(&handlers);
|
object_handlers_init(&handlers);
|
||||||
handlers.offset = sizeof(native_t);
|
handlers.offset = sizeof(native_t);
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#define PHP_ARMA_SUBVIEW_MAT_HH
|
#define PHP_ARMA_SUBVIEW_MAT_HH
|
||||||
|
|
||||||
#include "php_arma.hh"
|
#include "php_arma.hh"
|
||||||
|
#include "instantiable.hh"
|
||||||
#include "complex.hh"
|
#include "complex.hh"
|
||||||
|
|
||||||
namespace php_arma
|
namespace php_arma
|
||||||
|
@ -15,7 +16,7 @@ namespace php_arma
|
||||||
template <typename T> struct mat;
|
template <typename T> struct mat;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct subview_mat
|
struct subview_mat : instantiable<subview_mat<T>, true>
|
||||||
{
|
{
|
||||||
using native_t = arma::subview<T>;
|
using native_t = arma::subview<T>;
|
||||||
using orig_t = mat<T>;
|
using orig_t = mat<T>;
|
||||||
|
@ -25,13 +26,6 @@ namespace php_arma
|
||||||
|
|
||||||
friend void subview_mat_init();
|
friend void subview_mat_init();
|
||||||
|
|
||||||
template <typename... Ts>
|
|
||||||
zend_always_inline
|
|
||||||
static zend_object *create(Ts&&... args)
|
|
||||||
{
|
|
||||||
return object_create_ctor<native_t>(ce, &handlers, args...);
|
|
||||||
}
|
|
||||||
|
|
||||||
PHP_ARMA_CE_HANDLRES_DECLARE();
|
PHP_ARMA_CE_HANDLRES_DECLARE();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -18,5 +18,15 @@ batch_assert('read/write access of `MapVal`',
|
||||||
[7, $mat(0, 1)->val()]
|
[7, $mat(0, 1)->val()]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// When parent class is destroyed...
|
||||||
|
$orphaned_mapval = Arma\IMat::fromString('1 2; 3 4')->at(1, 1);
|
||||||
|
batch_assert('orphaned `MapVal`',
|
||||||
|
[$orphaned_mapval->val(), 4]
|
||||||
|
);
|
||||||
|
$orphaned_mapval->setTo(7);
|
||||||
|
batch_assert('orphaned `MapVal`',
|
||||||
|
[$orphaned_mapval->val(), 7]
|
||||||
|
);
|
||||||
|
|
||||||
?>
|
?>
|
||||||
--EXPECT--
|
--EXPECT--
|
||||||
|
|
|
@ -27,5 +27,13 @@ batch_assert('`SvMat`',
|
||||||
[PHP_INT_MAX, $mat->at(1, 2)->val()]
|
[PHP_INT_MAX, $mat->at(1, 2)->val()]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// When parent class is destroyed...
|
||||||
|
$orphaned_submat = Arma\IMat::fromString('1 2; 3 4')->cols(0, 0);
|
||||||
|
|
||||||
|
batch_assert('orphaned `SvMat`',
|
||||||
|
[$orphaned_submat->at(0, 0)->val(), 1],
|
||||||
|
[$orphaned_submat->at(1, 0)->val(), 3]
|
||||||
|
);
|
||||||
|
|
||||||
?>
|
?>
|
||||||
--EXPECT--
|
--EXPECT--
|
||||||
|
|
|
@ -18,9 +18,13 @@ $diag->rawPrint();
|
||||||
$diag->at(1)->setTo($diag->at(0)->val());
|
$diag->at(1)->setTo($diag->at(0)->val());
|
||||||
$mat->rawPrint();
|
$mat->rawPrint();
|
||||||
|
|
||||||
|
// When parent class is destroyed...
|
||||||
|
Arma\IMat::fromString("1 2; 3 4")->diag(-1)->rawPrint();
|
||||||
|
|
||||||
?>
|
?>
|
||||||
--EXPECT--
|
--EXPECT--
|
||||||
1
|
1
|
||||||
4
|
4
|
||||||
1 2
|
1 2
|
||||||
3 1
|
3 1
|
||||||
|
3
|
||||||
|
|
Reference in New Issue