I have seen docs about array indexing for basic types in cppyy. I haven't figured out how to index an array of custom types.
take:
import cppyy
cppyy.cppdef("""
struct Foo
{
float var;
}
struct Bar
{
Foo* foo;
}
""")
If an array of Foo objects is stored in an instance of Bar, how do I index that array to access the Foo element?
If I try:
bar.foo[0]
I get:
'Foo' object does not support indexing
EDIT 2: Following your suggestion in the comments below, the original code now works out-of-the-box with cppyy release 1.6.2. That is, if the Python proxy contains a pointer type, then indexing is taken to mean it represents an array.
As-is Foo* is taken as a pointer to Foo, not to an array of Foo. Yes, it could point to an array, but low-level C++ (C, really) is ambiguous and it being a pointer to an object is by far the common case. If something is an array, array syntax does work, as it becomes unambiguous again:
import cppyy
cppyy.cppdef("""
struct Foo
{
float var;
};
struct Bar
{
Foo foo[1];
};
""")
bar = cppyy.gbl.Bar()
print(len(bar.foo))
print(bar.foo[0])
which prints:
1
<cppyy.gbl.Foo object at 0x7f85ace370f0>
as expected.
If you don't know the length of the array, is there any option that you can use modern C++ constructs such as std::unique_ptr instead of heritage C? Those are completely unambiguous and thus easily automatically bound (they also make memory management a lot easier):
import cppyy
cppyy.cppdef("""
struct Foo
{
float var;
};
struct Bar
{
Bar(int num_foo) : foo(std::unique_ptr<Foo[]>{new Foo[num_foo]}) {
for (int i = 0; i < num_foo; ++i)
foo[i].var = (float)2.*i;
}
std::unique_ptr<Foo[]> foo;
};
""")
num_foo = 4
bar = cppyy.gbl.Bar(num_foo)
for i in range(num_foo):
print(bar.foo[i].var)
which prints the expected:
0.0
2.0
4.0
6.0
If you really are in the unenviable position of maintaining legacy code, I recommend patching things up a little with C++ (through the JIT with cppdef) and Python helpers (more details on pythonization here: https://cppyy.readthedocs.io/en/latest/pythonizations.html). For example:
import cppyy
cppyy.cppdef("""
struct Foo
{
float var;
};
struct Bar
{
Bar() : foo(new Foo{}) { foo[0].var = 42.f; }
// memory mgmt here ...
Foo* foo;
};
Foo* Bar_get_foo_indexed(Bar* b, int idx) {
return &b->foo[idx];
}
""")
# pythonize the getter
class FooGetter(object):
def __get__(self, obj, kls=None):
self.obj = obj
return self
def __getitem__(self, idx):
return cppyy.gbl.Bar_get_foo_indexed(self.obj, idx)
cppyy.gbl.Bar.foo = FooGetter()
bar = cppyy.gbl.Bar()
print(bar.foo[0].var)
which prints the expected:
42.0
EDIT: some more ideas based on your question. First, a casting example on the C++ side:
cppyy.cppdef("""
struct Foo
{
float var;
};
struct Bar
{
Bar() : foo(new Foo[2]) { foo[0].var = 42.f; foo[1].var = 13.f; }
// memory mgmt here ...
Foo* foo;
};
template<int N>
struct FooArrayWrapper {
Foo foo[N];
};
template<int N>
FooArrayWrapper<N>* cast_foo_array(Foo*& f) {
return reinterpret_cast<FooArrayWrapper<N>*>(f);
}
""")
def make_foo_wrapper_init(func):
def wrapper_init(self, foo_size, *args, **kwargs):
func(self)
self.__dict__['foo_array'] = cppyy.gbl.cast_foo_array[foo_size](self.foo).foo
return wrapper_init
cppyy.gbl.Bar.__init__ = make_foo_wrapper_init(cppyy.gbl.Bar.__init__)
bar = cppyy.gbl.Bar(2)
print(bar.foo_array[0].var)
print(bar.foo_array[1].var)
and a casting example using pointer arithmetic on the Python side:
cppyy.cppdef("""
struct Foo
{
float var;
};
struct Bar
{
Bar() : foo(new Foo[2]) { foo[0].var = 42.f; foo[1].var = 13.f; }
// memory mgmt here ...
Foo* foo;
};
""")
bar = cppyy.gbl.Bar()
for i in range(2):
print(cppyy.bind_object(cppyy.addressof(bar.foo)+i*cppyy.sizeof(cppyy.gbl.Foo), cppyy.gbl.Foo).var)
both print the expected:
42.0
13.0
Related
I'm attempting to implement a class that 'does' Positional that also allows me to update its values by assigning to the result returned by the AT-POS method. Eventually, I was able to concoct the following class that works as intended:
class Test does Positional
{
has $.slot_1 is rw = 12;
has $.slot_2 is rw = 24;
method AT-POS(\position)
{
my $t = self;
return-rw Proxy.new:
FETCH => method ()
{
position % 2 ?? $t.slot_1 !! $t.slot_2
},
STORE => method ($v)
{
if position % 2
{
$t.slot_1 = $v
}
else
{
$t.slot_2 = $v
}
}
}
}
my $test = Test.new;
die unless $test[2] == 24;
die unless $test[5] == 12;
$test[7] = 120;
die unless $test[2] == 24;
die unless $test[5] == 120;
$test[10] = 240;
die unless $test[2] == 240;
die unless $test[5] == 120;
Would it be possible to somehow (and: simply) return the container bound to $!slot_1 (or $!slot_2) inside the Test class implementation?
Before I discovered the use of Proxy instances I attempted to return (and return-rw) the result of expression position % 2 ?? $!slot_1.VAR !! $!slot_2.VAR, because I'm under the impression that the VAR method gives me access to the underlying container, in the hope that I can simply return it. That didn't really work, and I do not understand why yet: I suspect it somehow gets coerced back to a value somehow?
So in other words: is it possible to simplify my AT-POS implementation in this particular situation?
Thanks,
Regards,
Raymond.
Assuming you do not want accessors for "slot_1" and "slot_2", and if I understand the question correctly, this would be my implementation. I wouldn't call it a Test class, as that would interfere with the Test class that is used for testing.
class Foo {
has #elements = 24, 12;
method AT-POS(Int:D $pos) is raw {
#elements[$pos % 2]
}
}
my $f = Foo.new;
say $f[2]; # 24
say $f[5]; # 12
$f[2] = 666;
say $f[4]; # 666
Note that the defaults in the array have changed order, that's to keep the arithmetic in AT-POS simple.
Also note the is raw in the definition of the AT-POS method: it will ensure that no de-containerization will take place when returning a value. This allows you to just assign to whatever $f[2] returns.
Hope this made sense!
Also: the Array::Agnostic module may be of interest for you, to use directly, or to use as a source of inspiration.
First off if you aren't going to use an attribute outside of the object, there isn't a reason to declare them as public, and especially not rw.
class Foo {
has $!odd = 12;
has $!even = 24;
…
}
You can also directly return a Scalar container from a method. You should declare the method as rw or raw. (raw doesn't guarantee that it is writable.)
class Foo {
has $!odd = 12;
has $!even = 24;
method AT-POS(\position) is rw {
position % 2 ?? $!odd !! $!even
}
}
# we actually get the Scalar container given to us
say Foo.new[10].VAR.name; # $!even
Note that even if you declare the attributes as public they still have a private name. The private attribute is always rw even if it isn't publicly declared as rw.
class Foo {
has $.odd = 12;
has $.even = 24;
method AT-POS(\position) is rw {
position % 2 ?? $!odd !! $!even
}
}
If you are going to use a Proxy, I would consider moving the common code outside of it.
class Foo {
has $.odd = 12;
has $.even = 24;
method AT-POS(\position) is rw {
# no need to write this twice
my $alias := (position % 2 ?? $!odd !! $!even);
Proxy.new:
FETCH => method () { $alias },
STORE => method ($new-value) { $alias = $new-value }
}
}
Of course the ?? !! code is a core feature of this module, so it would make sense to put it into a single method so that you don't end up with duplicate code all over your class. In this case I made it a private method.
class Foo {
has $.odd = 12;
has $.even = 24;
# has to be either `raw` or `rw`
# it is debatable of which is better here
method !attr(\position) is raw {
position % 2 ?? $!odd !! $!even
}
method AT-POS(\position) is rw {
my $alias := self!attr(position);
Proxy.new:
FETCH => -> $ { $alias },
STORE => -> $, $new-value { $alias = $new-value }
}
}
Again, not much reason to use a Proxy.
class Foo {
has $.odd = 12;
has $.even = 24;
method !attr(\position) is raw {
position % 2 ?? $!odd !! $!even
}
method AT-POS(\position) is rw {
self!attr(position);
}
}
Instead of ?? !! you could use an indexing operation.
method !attr(\position) is raw {
($!even,$!odd)[position % 2]
}
Which would allow for a ternary data structure.
method !attr(\position) is raw {
($!mod0,$!mod1,$!mod2)[position % 3]
}
There was no need to write the if statement that you did as Raku usually passes Scalar containers around instead of the value.
(position % 2 ?? $t.slot_1 !! $t.slot_2) = $v;
Noob question:
I want to mutate a value that exists in an array list. I initially tried to just grab the indexed item and directly change its field value.
const Foo = struct {
const Self = #This();
foo: u8,
};
pub fn main() anyerror!void {
const foo = Foo {
.foo = 1,
};
const allocator = std.heap.page_allocator;
var arr = ArrayList(Foo).init(allocator);
arr.append(foo) catch unreachable;
var a = arr.items[0];
std.debug.warn("a: {}", .{a});
a.foo = 2;
std.debug.warn("a: {}", .{a});
std.debug.warn("arr.items[0]: {}", .{arr.items[0]});
//In order to update the memory in [0] I have to reassign it to a.
//arr.items[0] = a;
}
However, the result is unexpected to me:
a: Foo{ .foo = 1 }
a: Foo{ .foo = 2 }
arr.items[0]: Foo{ .foo = 1 }
I would have thought that arr.items[0] would now equal Foo{ .foo = 2 }.
This is probably because I misunderstand slices.
Does a not point to the same memory as arr.items[0]?
Does arr.items[0] return a pointer to a copied item?
var a = arr.items[0];
That is making a copy of the item in arr.items[0].
If you want a reference, write var a = &arr.items[0]; instead.
I currently use CGAL to generate 2D Delaunay triangulation.One of the mesh control parameter is the maximum length of the triangle edge. The examples suggests that this parameter is a constant. I would like to know how this parameter be made function of some thing else, for example spatial location.
I think Delaunay meshing with variable density is not directly supported by CGAL although you could mesh your regions independently. Alternatively you may have a look at: http://www.geom.at/advanced-mesh-generation/ where I have implemented that as a callback function.
It doesn't look like CGAL provides an example of this but they machinery is all there. The details get a little complicated since the objects that control if triangles need to be refined also have to understand the priority under which triangles get refined.
To do this, I copied Delaunay_mesh_size_criteria_2 to create a new class (Delaunay_mesh_user_criteria_2) that has a spatially varying sizing field. Buried in the class is a function (user_sizing_field) that can be implemented with a varying size field based on location. The code below compares the size of the longest edge of the triangle to the minimum of the sizing field at the three vertices, but you could use a size at the barycenter or circumcenter or even send the entire triangle to the sizing function if you have a good way to compute the smallest allowable size on the triangle altogether.
This is a starting point, although a better solution would,
refactor some things to avoid so much duplication with with existing Delaunay_mesh_size_criteria,
allow the user to pass in the sizing function as an argument to the criteria object, and
be shipped with CGAL.
template <class CDT>
class Delaunay_mesh_user_criteria_2 :
public virtual Delaunay_mesh_criteria_2<CDT>
{
protected:
typedef typename CDT::Geom_traits Geom_traits;
double sizebound;
public:
typedef Delaunay_mesh_criteria_2<CDT> Base;
Delaunay_mesh_user_criteria_2(const double aspect_bound = 0.125,
const Geom_traits& traits = Geom_traits())
: Base(aspect_bound, traits){}
// first: squared_minimum_sine
// second: size
struct Quality : public std::pair<double, double>
{
typedef std::pair<double, double> Base;
Quality() : Base() {};
Quality(double _sine, double _size) : Base(_sine, _size) {}
const double& size() const { return second; }
const double& sine() const { return first; }
// q1<q2 means q1 is prioritised over q2
// ( q1 == *this, q2 == q )
bool operator<(const Quality& q) const
{
if( size() > 1 )
if( q.size() > 1 )
return ( size() > q.size() );
else
return true; // *this is big but not q
else
if( q.size() > 1 )
return false; // q is big but not *this
return( sine() < q.sine() );
}
std::ostream& operator<<(std::ostream& out) const
{
return out << "(size=" << size()
<< ", sine=" << sine() << ")";
}
};
class Is_bad: public Base::Is_bad
{
public:
typedef typename Base::Is_bad::Point_2 Point_2;
Is_bad(const double aspect_bound,
const Geom_traits& traits)
: Base::Is_bad(aspect_bound, traits) {}
Mesh_2::Face_badness operator()(const Quality q) const
{
if( q.size() > 1 )
return Mesh_2::IMPERATIVELY_BAD;
if( q.sine() < this->B )
return Mesh_2::BAD;
else
return Mesh_2::NOT_BAD;
}
double user_sizing_function(const Point_2 p) const
{
// IMPLEMENT YOUR CUSTOM SIZING FUNCTION HERE.
// BUT MAKE SURE THIS RETURNS SOMETHING LARGER
// THAN ZERO TO ALLOW THE ALGORITHM TO TERMINATE
return std::abs(p.x()) + .025;
}
Mesh_2::Face_badness operator()(const typename CDT::Face_handle& fh,
Quality& q) const
{
typedef typename CDT::Geom_traits Geom_traits;
typedef typename Geom_traits::Compute_area_2 Compute_area_2;
typedef typename Geom_traits::Compute_squared_distance_2 Compute_squared_distance_2;
Geom_traits traits; /** #warning traits with data!! */
Compute_squared_distance_2 squared_distance =
traits.compute_squared_distance_2_object();
const Point_2& pa = fh->vertex(0)->point();
const Point_2& pb = fh->vertex(1)->point();
const Point_2& pc = fh->vertex(2)->point();
double size_bound = std::min(std::min(user_sizing_function(pa),
user_sizing_function(pb)),
user_sizing_function(pc));
double
a = CGAL::to_double(squared_distance(pb, pc)),
b = CGAL::to_double(squared_distance(pc, pa)),
c = CGAL::to_double(squared_distance(pa, pb));
double max_sq_length; // squared max edge length
double second_max_sq_length;
if(a<b)
{
if(b<c) {
max_sq_length = c;
second_max_sq_length = b;
}
else { // c<=b
max_sq_length = b;
second_max_sq_length = ( a < c ? c : a );
}
}
else // b<=a
{
if(a<c) {
max_sq_length = c;
second_max_sq_length = a;
}
else { // c<=a
max_sq_length = a;
second_max_sq_length = ( b < c ? c : b );
}
}
q.second = 0;
q.second = max_sq_length / (size_bound*size_bound);
// normalized by size bound to deal
// with size field
if( q.size() > 1 )
{
q.first = 1; // (do not compute sine)
return Mesh_2::IMPERATIVELY_BAD;
}
Compute_area_2 area_2 = traits.compute_area_2_object();
double area = 2*CGAL::to_double(area_2(pa, pb, pc));
q.first = (area * area) / (max_sq_length * second_max_sq_length); // (sine)
if( q.sine() < this->B )
return Mesh_2::BAD;
else
return Mesh_2::NOT_BAD;
}
};
Is_bad is_bad_object() const
{ return Is_bad(this->bound(), this->traits /* from the bad class */); }
};
I am also interested for variable mesh criteria on the domaine with CGAL. I have found an alternative many years ago : https://www.cs.cmu.edu/~quake/triangle.html
But i am still interested to do the same things with CGAL ... I don't know if it is possible ...
I ve got a problem with allocating cli::array in function.
I have this kind of object:
array<double>^ tmsr2;
now I want to allocate it in function so:
void allocate(array<double>^ tmsr2)
{
tmsr2=gcnew array<double>(100);
}
Now, tmsr2 in function gets allocated well but I lose the pointer when returning to main()
The problem is clear to me, just like if I want to allocate simple array "double *a"; I need to pass pointer to function so "&a" and then everything works fine. I just don't know the syntax with managed arrays. Help much appreciated.
Peter
Since array<double> is a managed type, you can use a managed tracking reference here, instead of a plain reference.
void allocate(array<double>^% tmsr2)
{
tmsr2 = gcnew array<double>(100);
}
Here's my test app:
public ref class AsAClassField
{
public:
array<double>^ b;
AsAClassField()
{
allocate(b);
Debug::WriteLine("b = " + (b != nullptr ? "array" : "null"));
}
};
int main(array<System::String ^> ^args)
{
array<double>^ a = nullptr;
allocate(a);
Debug::WriteLine("a = " + (a != nullptr ? "array" : "null"));
AsAClassField^ foo = gcnew AsAClassField();
return 0;
}
Output:
a = array
b = array
Of course, you could always switch your allocate function to return the newly allocated array, rather than taking it as a reference. That would be more in the managed style.
You can pass the array as a reference:
void allocate(array<double>^ &tmsr2)
{
tmsr2=gcnew array<double>(100);
}
I'd like to pass some numeric byte values via an initializer list a variadic template into an array. Is that possible?
template < int N > struct a {
char s[N];
template < typename ... A >
a (A ... _a) : s {_a...} {}
};
int main () {
// g++-4.5: error: narrowing conversion of »_a#0« from »int« to »char« inside { }
a < 3 > x { 1, 2, 3 };
}
What I can think of is
to use octal representation, '\001' etc., or
to cast every single value.
But both is not satisfying.
You don't need any complicated code
template < int N > struct a {
char s[N];
template < typename ... A >
a (A ... _a) : s {static_cast<char>(_a)...} {}
};
NOTE: All of this is unnecessary unless you have added functionality to the class so it's no longer an aggregate. (For example, other constructors, private members, a base class, etc.) The immediate way to fix the code in the question is simply to remove the constructor. So, let's assume there's something more to it.
I've seen some people trying to do things like this. It seems ugly, dealing with conversion semantics and trying to artificially re-create the functionality of a usual function call.
Here is a strategy to create an array class that simply has the right constructor in the first place.
Template aliasing would put the icing on the cake by hiding the ::type ugliness, but it's not in GCC yet.
template< typename ... NT >
struct var_ctor_array {
enum { size_e = 0 }; // only used for zero size case
};
template< typename T, typename ... NT >
struct var_ctor_array< T, NT ... > {
enum { size_e = 1 + sizeof...( NT ) };
T st[ size_e ];
var_ctor_array( T elem0, NT ... elemN )
: st { elem0, elemN ... } {}
};
template< typename T, size_t N, typename ... NT >
struct gen_var_ctor_array {
typedef typename gen_var_ctor_array< T, N-1, T, NT ... >::type type;
};
template< typename T, typename ... NT >
struct gen_var_ctor_array< T, 0, NT ... > {
typedef var_ctor_array< NT ... > type;
};
int main() { // usage
gen_var_ctor_array< char, 5 >::type five( 1, 2, 3, 4, 5 );
}
You're not actually using initializer lists. The constructor receives a variadic template and you initialize x with uniform initialization.
The only problem is I don't know of an elegant way of initializing an array with an initializer_list, AFAIK std::array should have a constructor that accepts initializer_list but it doesn't seem to be supported by g++ yet.
#include <utility>
template < int N > struct a {
char s[N];
a (std::initializer_list<char> list) {
if (N != list.size())
throw "list wrong size";
int i = 0;
const char* p = list.begin();
while(p != list.end())
s[i++] = *p++;
}
};