How to register a new type in GType in vala? - glib

I found some type non listed in the GLib.Type, if I want to create and register an new type in GType, how to implement it?
I mean the integer types are not listed:
https://valadoc.org/gobject-2.0/GLib.Type.html
public const Type INT8
public const Type INT16
public const Type INT32
public const Type INT64
public const Type INT128
public const Type UINT8
public const Type UINT16
public const Type UINT32
public const Type UINT64
public const Type UINT128
and there are many boxed type not defined in GLib.Type:
https://developer.gnome.org/gobject/stable/gobject-Boxed-Types.html

Type.INT64 and Type.UINT64 are already there. See the declarations in the Type struct in the gobject-2.0.vapi. Adding the other basic types to that VAPI shouldn't be a problem. Submit a pull request to Vala's GitLab instance.
The boxed types you list should also be fairly simple to add. You might want to check the C header glib-object.h and submit it as a separate commit just in case there is a complication.
It looks like these are pre-defined types used by the GObject runtime type system. New types can be declared separately at runtime and Vala deals with that behind the scenes when you create your own types.

Related

Dart: A value of type 'int' can't be assigned to a variable of type 'int' [duplicate]

This question already has answers here:
The argument type 'String' can't be assigned to the parameter type 'String'
(3 answers)
Closed 1 year ago.
When I write an extension like so:
extension MyExtension<int> on List<int> {
void myMethod() {
int a = 1; // error
}
}
I get a seemingly nonsensical error message from the compiler:
A value of type 'int' can't be assigned to a variable of type 'int'.
Try changing the type of the variable, or casting the right-hand type to 'int'. dart(invalid_assignment)
I can fix the problem by removing <int> after the extension name:
extension MyExtension on List<int> {
void myMethod() {
int a = 1;
}
}
But I'd like to know what was going on in the original problematic code. What was the reason for the cryptic error message?
So you are having a simple problem, you are reassigning the meaning of int
extension MyExtension<int> on List<int>
Your extension takes a type argument, which means that when using the extension, you can pass many different types to it, but the name of this new type argument is int.
So you are assigning an int (the number) to int (the type argument) which is impossible because dart does not know if int (the type argument) will be an int.
In order to fix this, you can remove the type argument as you did, the code you show does not need a type argument, you can also rename the type argument, the convention says type arguments should be called T:
extension MyExtension<T> on List<int> ...
if what you want is for the type argument to always be an int, or a class that extends int you can also declare that:
extension MyExtension<T extends int> on List<int> ...
If you still have trouble understanding what type arguments are and how they work, here is the documentation for type arguments and here is the documentation for extensions with type arguments

Get type of Key and Value from a Map variable?

Given a Map variable, how can I determine the type of Key and Value from it?
For example:
void doSomething(Map m){
print('m: ${m.runtimeType}');
print('keys: ${m.keys.runtimeType}');
print('values: ${m.values.runtimeType}');
print('entries: ${m.entries.runtimeType}');
}
void main() async {
Map<String, int> m = {};
doSomething(m);
}
This will print
m: _InternalLinkedHashMap<String, int>
keys: _CompactIterable<String>
values: _CompactIterable<int>
entries: MappedIterable<String, MapEntry<String, int>>
But how can I get the actual type of Key and Value (i.e. String and int), so that I can use them in type checking code (i.e. if( KeyType == String ))?
You cannot extract the type parameters of a class if it doesn't provide them to you, and Map does not.
An example of a class which does provide them is something like:
class Example<T> {
Type get type => T;
R withType<R>(R Function<X>() callback) => callback<T>();
}
If you have an instance of Example, you can get to the type parameter, either as a Type (which is generally useless), or as a type argument which allows you to do anything with the type.
Alas, providing access to types variables that way is very rare in most classes.
You can possibly use reflection if you have access to dart:mirrors, but most code does not (it doesn't work with ahead-of-time compilation, which includes all web code, or in Flutter programs).
You can try to guess the type by trying types that you know (like map is Map<dynamic, num>, then map is Map<dynamic, int> and map is Map<dynamic, Never>. If the first two are true, and the last one is false, then the value type is definitely int. That only works if you know all the possible types.
It does work particularly well for platform types like int and String because you know for certain that their only subtype is Never.
If you can depend on the static type instead of the runtime type, you could use a generic function:
Type mapKeyType<K, V>(Map<K, V> map) => K;
Otherwise you would need to have a non-empty Map and inspect the runtime types of the actual elements.

What is the difference between constant named constructor and static constant field below?

What is the difference between a and b below?
class ImmutablePoint {
const ImmutablePoint(this.x, this.y);
final int x;
final int y;
const ImmutablePoint.originA() : this(0, 0);
static const ImmutablePoint originB = const ImmutablePoint(0, 0);
}
void main() {
const a = ImmutablePoint.originA();
const b = ImmutablePoint.originB;
}
The constant variable defines and names a single value.
The const constructor defines a way to create new values.
If that constructor is invoked as const ImmutablePoint.originA() then, because of constant canonicalization, it creates the same constant value that the variable contains. However, you can also call new ImmutablePoint.originA() (with or without the new) and get a new instance which is not identical to any other point object.
A Dart constructor being const means that it can be invoked using const, not that it must.
From a literal perspective, one is a constructor and the other is a static variable. The constructor allows you to define constants, and the static variable already is a constant. That much should be fairly self-explanatory.
From a performance perspective? Both values resolve to the same constant-defined object:
const ImmutablePoint(0, 0);
Thanks to Dart's canonical constant feature, everything that references this constant class with the same values 0,0 (including other calls to ImmutablePoint.originA() or even ImmutablePoint(0, 0)) will be reduced to point to the same compile-time constant. So from a practical point of view, both the parameterless const constructor and the static const variable result in virtually identical compiled code and, therefore, performance.
(Though from a strictly nit-picky point of view, the static const might be compiled to include a static reference to the ImmutablePoint type before referencing the constant. I'm not knowledgeable enough with how Dart compiles these situations to say that for certainty, but I can tell you that even if it does happen, the performance hit for a static type reference will be in the "nanoseconds-or-less" tier of negligible. Don't micro-optimize, just use whatever approach you deem more readable or convenient.)

Dart passing types to functions fails

I have a map consisting of different types and strings:
const Map<Type, String> hiveTableNames = {
BreakTimeDto: "breaktime",
WorkTimeDto: "worktime"
};
And I want to loop through it because I want to call a function for each type which takes a type parameter:
Future<void> sendAll<T>(List item) async {
...
}
My attempt was to use the forEach-loop:
hiveTableNames.forEach((key, value) async {
final box = await Hive.openBox(value);
_helper.sendAll<key>(box.values.cast<key>().toList());
});
But the App throws an error: Error: 'key' isn*t a type.
Why is that? I declared the map to store types and from my understanding i pass these types in the function.
Dart separates actual types and objects of type Type. The latter are not types, and cannot be used as types, they're more like mirrors of types. A Type object can only really be used for two things: as tokens to use with dart:mirrors and comparing for equality (which isn't particularly useful except for very simple types).
The only things that can be used as type arguments to generic functions or classes are actual literal types or other type variables.
In your case, you have a Type object and wants to use the corresponding type as a type argument. That won't work, there is no way to go from a Type object to a real type.
That's a deliberate choice, it means that the compiler can see that if a type is never used as a type argument in the source code, then it will never be the type bound to a type parameter, so if you have foo<T>(T value) => ... then you know that T will never be Bar if Bar doesn't occur as a type argument, something<Bar>(), anywhere in the program.
In your case, what you can do is to keep the type around as a type by using a more complicated key object.
Perhaps:
class MyType<T> {
const MyType();
R use<R>(R Function<X>() action) => action<T>();
int get hashCode => T.hashCode;
bool operator==(Object other) => other is MyType && other.use(<S>() => T == S);
}
This allows you to store the type as a type:
final Map<MyType, String> hiveTableNames = {
const MyType<BreakTimeDto>(): "breaktime",
const MyType<WorkTimeDto>(): "worktime"
};
(I'm not making the map const because const maps must not have keys which override operator==).
Then you can use it as:
hiveTableNames.forEach((key, value) async {
final box = await Hive.openBox(value);
key.use(<K>() =>
_helper.sendAll<K>([for (var v in box.values) v as K]);
}
(If all you are using your map for is iterating the key/value pairs, then it's really just a list of pairs, not a map, so I assume you are using it for lookups, which is why MyType override operator==).
In general, you should avoid using Type objects for anything, they're very rarely the right tool for any job.

type TMessage is not a defined class with virtual function C++ builder sample

Im trying to use embarcadero sample on useing android camera and geting an error:
"type TMessage is not a defined class with virtual function" on lines:
void __fastcall TForm1::DoMessageListener(const TObject *Sender, TMessage const *M) {
TMessageDidFinishTakingImageFromLibrary const *v = dynamic_cast<TMessageDidFinishTakingImageFromLibrary const *>(M);
if (v) {
Image1->Bitmap->Assign(v->Value);
}
}
In Delphi, TMessage works fine, but in C++Builder you must use TMessageBase instead:
void __fastcall TForm1::DoMessageListener(const TObject *Sender, TMessageBase const *M)
This is clearly stated in the documentation:
Sending and Receiving Messages Using the RTL:
The RTL only defines one type of message, TMessage. It is actually a template that you can use to create messages for specific types of values; for example: TMessage<int> or TMessage<UnicodeString>. You can also subclass TMessage to define your own message types or, if you are using FireMonkey, you can reuse the message types defined by the framework.
Note: For C++ projects use TMessageBase instead of TMessage.
System.Messaging.TMessage
TMessage represents the base class used for message purposes. It can be inherited in order to send custom messages.
Warning: For C++ projects, use TMessageBase instead.
System.Messaging.TMessageBase
Alias to System.Messaging.TMessage.
Use System.Messaging.TMessageBase for C++ projects instead of System.Messaging.TMessage.
This use of TMessageBase is also demonstrated in the documentation's System.Messaging (C++) example.

Resources