I have a class that has fields and I want call a method of this class and get the reference to one of the fields (not the value!!). Something like this:
class Test : Object{
uint8 x;
uint8 y;
uint8 z;
uint8 method(){
if (x == 1){
return y;
}else if (x == 2){
return z;
}
}
public static void main(string[] args){
uint8 i = method(); // get reference to y or z
i++; //this must update y or z
}
}
In C would be:
int& method()
{
if (x == 1){
return y;
}else if (x == 2){
return z;
}
}
How can I achieve this in vala?
Edit: I'm trying use pointers, I have the following
public class Test : Object {
private Struct1 stru;
struct Struct1{
uint8 _a;
public uint8 a{
get{ return _a; }
set{ _a = value; }
}
public Struct1(Struct1? copy = null){
if (copy != null){
this._a = copy.a;
}else{
this._a = 0;
}
}
public uint8* get_aa(){
return (uint8*)a;
}
}
public void get_pointer(){
uint8* dst = stru.get_aa();
}
public static int main (string[] args){
Test t = new Test();
return 0;
}
}
but when I compile I get
/home/angelluis/Documentos/vala/test.vala.c: In function ‘test_struct1_get_aa’:
/home/angelluis/Documentos/vala/test.vala.c:130:11: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
result = (guint8*) _tmp1_;
^
Compilation succeeded - 2 warning(s)
Why? I am returning an uint8* type and I attempt to store it in an uint8* pointer.
C doesn't have references (C++ does). Keep in mind that Vala compiles to C as an intermediate language.
I think that there are only two ways to do this in Vala:
Use a box type to encapsulate your uint8 values and return a reference to that box type.
Use a pointer. (Which opens the obvious pointer can of worms)
Edit: Answer to your updated example code problem:
You must be very careful with casting something to some pointer type. In this case the C compiler caught your spurious cast and emited a warning.
uint8 _a;
// This property will get and set the *value* of _a
public uint8 a{
get{ return _a; }
set{ _a = value; }
}
public uint8* get_aa(){
// Here you are casting a *value* of type uint8 to a pointer
// Which doesn't make any sense, hence the compiler warning
return (uint8*)a;
}
Note that you can't get a pointer or a reference to a property, because properties have no memory location on their own.
You can however get a pointer to the field _a in this case:
public uint8* get_aa(){
return &_a;
}
If you insist to go through the property, you have to make your property operate on the pointer as well:
uint8 _a;
public uint8* a{
get{ return &_a; }
}
Notice that in this version I have removed the get_aa () method which is now equivalent to the getter for a.
Also since in this code the property is returning a pointer there is no need for a setter, you can just dereference the pointer to set the value.
Related
I trying make the following code but T only can be int, double or a custom class. I couldn't find how to restrict the type in Dart or something that work like where from C#. How can I do that in Dart?
class Array3dG<T> extends ListBase<T> {
List<T> l = List<T>();
Array3dG(List<T> list) {
l = list;
}
set length(int newLength) { l.length = newLength; }
int get length => l.length;
T operator [](int index) => l[index];
void operator []=(int index, T value) { l[index] = value; }
}
There is no way to constrain the type variable at compile-time. You can only have one bound on a type variable, and the only bound satisfying both int and your custom class is Object.
As suggested by #Mattia, you can check at run-time and throw in the constructor if the type parameter is not one of the ones you supprt:
Array3dG(this.list) {
if (this is! Array3dG<int> &&
this is! Array3dG<double> &&
this is! Array3dG<MyClass>) {
throw ArgumentError('Unsupported element type $T');
}
}
This prevents creating an instance of something wrong, but doesn't catch it at compile-time.
Another option is to have factory methods instead of constructors:
class Array3dG<T> {
List<T> list;
Array3dG._(this.list);
static Array3dG<int> fromInt(List<int> list) => Array3dG<int>._(list);
static Array3dG<int> fromDouble(List<double> list) => Array3dG<double>._(list);
static Array3dG<MyClass> fromMyClass(List<MyClass> list) => Array3dG<MyClass>._(list);
...
}
which you then use as Array3dG.fromInt(listOfInt). It looks like a named constructor, but it is just a static factory method (so no using new in front).
You can check at runtime the type with the is keyword:
Array3dG(List<T> list) {
if (list is List<int>) {
//Handle int
}
else if (list is List<double>) {
//Handle double
}
else if (list is List<MyClass>) {
//Handle MyClass
}
else {
throw ArgumentError('Unsupported $T type');
}
}
Note that if you are handling int and double in the same way you can just check for num
You can check the progress of the Union types here: https://github.com/dart-lang/sdk/issues/4938
I can conveniently change opsCount variable directly from inside the function,
because there is only one of that type of variable.
int opsCount = 0;
int jobXCount = 0;
int jobYCount = 0;
int jobZCount = 0;
void doStats(var jobCount) {
opsCount++;
jobCount++;
}
main() {
doStats(jobXCount);
}
But there are many jobCount variables, so how can I change effectively that variable, which is used in parameter, when function is called?
I think I know what you are asking. Unfortunately, the answer is "you can't do this unless you are willing to wrap your integers". Numbers are immutable objects, you can't change their value. Even though Dart's numbers are objects, and they are passed by reference, their intrinsic value can't be changed.
See also Is there a way to pass a primitive parameter by reference in Dart?
You can wrap the variables, then you can pass them as reference:
class IntRef {
IntRef(this.val);
int val;
#override
String toString() => val.toString();
}
IntRef opsCount = new IntRef(0);
IntRef jobXCount = new IntRef(0);
IntRef jobYCount = new IntRef(0);
IntRef jobZCount = new IntRef(0);
void doStats(var jobCount) {
opsCount.val++;
jobCount.val++;
}
main() {
doStats(jobXCount);
print('opsCount: $opsCount; jobXCount: $jobXCount; jobYCount: $jobYCount; jobZCount: $jobZCount');
}
EDIT
According to Roberts comment ..
With a custom operator this would look like:
class IntRef {
IntRef(this.val);
int val;
#override
String toString() => val.toString();
operator +(int other) {
val += other;
return this;
}
}
void doStats(var jobCount) {
opsCount++;
jobCount++;
}
class AbstractStack
{
public :
virtual bool push(int n) = 0;// push n to the stack. If the stack is full, return false
virtual bool pop(int& n) = 0;// store the integer that popped from the stack to n,if the stack is empty return false.
virtual int size() = 0; //return number of integers that has been stored to the stack
}
Inheriting class AbstractStack, how can I create "class IntStack" where it 'pushes' and 'pops' integer?
I've so far tried
class IntStack : public AbstractStack{
bool push(int n);
bool pop(int &n);
}
Because there's a few pure-virtual methods (that's what the = 0 does) this means that any derived class must implement these methods.
AbstractStack defines an interface to manipulate your user-defined Stack types. This means that the code can use the same syntax to access the different types of Stack with different underlying types.
So given this:
class AbstractStack{
public :
virtual bool push(int n) = 0;
virtual bool pop(int& n) = 0;
virtual int size() = 0;
};
You would want to do something like this:
class IntStack: public AbstractStack{
public:
bool push(int n){
//implement the push() for Ints here
}
bool pop(int& n){
//implement the pop() for Ints here
}
int size(){
//implement the size() for Ints here
}
private:
//Here you need to specify the underlying storage type that this class uses
//to store the stack of int's
stack_t m_stack;
}; //Don't forget the trailing ;!
Consider the following code which prints out the even numbers up to 20:
import std.stdio;
class count_to_ten{
static int opApply()(int delegate(ref int) dg) {
int i = 1;
int ret;
while(i <= 10){
ret = dg(i);
if(ret != 0) {
break;
}
i++;
}
return ret;
}
}
void main() {
int y = 2;
foreach(int x; count_to_ten) {
writeln(x * y);
}
}
The syntax of opApply requires that it take a delegate or function as a normal argument. However, even if we relaxed that and allowed opApply to take a function as a template argument, we still would have no recourse for delegates because D doesn't provide any way to separate the stack-frame pointer from the function pointer. However, this seems like it should be possible since the function-pointer part of the delegate is commonly a compile-time constant. And if we could do that and the body of the loop was short, then it could actually be inlined which might speed this code up quite a bit.
Is there any way to do this? Does the D compiler have some trick by which it happens automagically?
I like Dart, so I've been writing a small WebGL game. I have a Shaders class which is pretty basic:
class Shaders {
static final int FRAGMENT = 0;
static final int VERTEX = 1;
HashMap<String, webGL.UniformLocation> _uniforms;
webGL.Program _program;
webGL.Shader _vertShader;
webGL.Shader _fragShader;
webGL.RenderingContext _gl;
Shaders(this._gl) {
_uniforms = new HashMap();
_program = _gl.createProgram();
_vertShader = _gl.createShader(webGL.VERTEX_SHADER);
_fragShader = _gl.createShader(webGL.FRAGMENT_SHADER);
}
Future<String> loadSource(String filename) {
return HttpRequest.getString(filename);
}
void compileSource(int type, String data) {
if (type == VERTEX) {
_gl.shaderSource(_vertShader, data);
_gl.compileShader(_vertShader);
_gl.attachShader(_program, _vertShader);
if (!_gl.getShaderParameter(_vertShader, webGL.COMPILE_STATUS))
print("Vertex shader: ${_gl.getShaderInfoLog(_vertShader)}");
} else if (type == FRAGMENT) {
_gl.shaderSource(_fragShader, data);
_gl.compileShader(_fragShader);
_gl.attachShader(_program, _fragShader);
if (!_gl.getShaderParameter(_fragShader, webGL.COMPILE_STATUS))
print("Vertex shader: ${_gl.getShaderInfoLog(_fragShader)}");
}
}
void setUniformMatrix(String name, var mat) {
//if we dont have this uniform get it and store for later
if (!_uniforms.containsKey(name)) {
var loc = _gl.getUniformLocation(_program, name);
_uniforms[name] = loc;
}
_gl.uniformMatrix4fv(_uniforms[name], false, mat.data());
}
void bindAttribute(int index, String name) {
_gl.bindAttribLocation(_program, index, name);
}
void useShader() {
_gl.linkProgram(_program);
_gl.useProgram(_program);
}
}
I also have a RenderComponent class that I give to entities when they should be drawable.
It looks like this (these classes aren't done):
abstract class Component {
static final int RENDER = 1;
int _type;
Component(this._type);
int get type => _type;
}
class RenderComponent extends Component {
BufferObject _vbo;
Shaders _shader;
RenderComponent() : super(Component.RENDER);
set shader(Shaders s) => _shader = s;
set buffer(BufferObject v) => _vbo = v;
Shaders get shader => _shader;
BufferObject get buffer => _vbo;
}
When I create an object of RenderComponent and set the shader like this:
var s = new Shaders(pass in gl context);
var r = new RenderComponent();
r.shader = s;
I get this error message:
Breaking on exception: type 'Shaders' is not a subtype of type 'Shaders' of 's'.
Google didn't come up with anything that makes sense to me. This is the most unhelpful message I've ever come across, and I can't get past it. Does anyone know what is causing this?