i am trying to figure out how the code behind a basic kernel driver works.
I have the following struct:
static struct file_operations fops =
{
.open = dev_open,
.read = dev_read,
.write = dev_write,
.release = dev_release,
};
And my dev_open function is defined as:
static int dev_open(struct inode *, struct file *);
Now Im also familiar with the fact that the prototype for opening a device file is defined in the linux/fs.h:
http://lxr.linux.no/linux+v3.10/include/linux/fs.h#L1517
Here is the specific line from that link:
int (*open) (struct inode *, struct file *);
Now my question is what is the relationship between .open = dev_open, and int (*open) (struct inode *, struct file *);
which is defined in linux/fs.h? Is it passing the address of dev_open to the function pointer int (*open) defined in the linux/fs.h? There must be some relation or what is the point of defining the struct fops as type "file operation"?
A similar question was asked and answered here but i feel that my question was left out:
File operations in drivers
Thank you
I think this question is more about C than the Linux kernel.
Members of structure or union types cannot have function type, but they can have pointer to function type. For example, in the Linux kernel, the open member of struct file_operations needs to be declared with a pointer to function type: int (*open)(struct inode *, struct file *);. Declaring the member as int open(struct inode *, struct file *); is an error.
In this variable definition in Linux kernel code:
static struct file_operations fops =
{
.open = dev_open,
.read = dev_read,
.write = dev_write,
.release = dev_release,
};
Incidentally, the above should normally have the owner member initialized like so:
.owner = THIS_MODULE,
The expressions dev_open, dev_read, dev_write and dev_release are function designators being used as assignment expressions to initialize the members of fops. A function designator is an expression that has function type. Unless it is the operand of sizeof, _Alignof, or the unary & operator, a function designator is converted to a pointer to function type. Therefore, the above definition of variable foo is exactly equivalent to:
static struct file_operations fops =
{
.open = &dev_open,
.read = &dev_read,
.write = &dev_write,
.release = &dev_release,
};
(Don't forget to also initialize .owner = THIS_MODULE,.)
There, the function designators are operands of the unary & operator and so are not converted to pointer to function types implicitly, but the & operator is converting them to pointer to function types explicitly.
After the above initialization of fops, rc = fops.open(inode, file); indirectly calls dev_open(inode, file) and assigns the return value to rc. You may sometimes see this written in an older style: rc = (*fops.open)(inode, file);. They both do the same thing. The operand of the function call operator ( ) is in fact always a pointer to a function. In the case of rc = (*fops.open)(inode, file);, fops.open has a pointer to a function type. (*fops.open) dereferences fops.open to a function type but since (*fops.open) is a function designator it is implicitly converted back to a pointer to function type before the function call. Similarly, in the direct call rc = dev_open(inode, file);, dev_open is a function designator and so has a function type, but is implicitly converted to a pointer to function type before the function call.
Consider the following program:
[<Struct>]
type Grid2D<'T> =
val RowLength : int
val Data : 'T[]
new(rowLength, data) = { RowLength = rowLength; Data = data }
member this.Item
with get(rowIndex, columnIndex) =
this.Data.[rowIndex * this.RowLength + columnIndex]
and set(rowIndex, columnIndex) value =
this.Data.[rowIndex * this.RowLength + columnIndex] <- value
let g = Grid2D(3, Array.zeroCreate(3 * 3))
g.[1, 1] <- 4
The last line fails to compile with:
error FS0256: A value must be mutable in order to mutate the contents
or take the address of a value type, e.g. 'let mutable x = ...'
However, if the [<Struct>] attribute is removed, and Grid2D is thus a reference type, then the program compiles.
Interestingly, inlining the property setter by hand also compiles fine:
g.Data.[1 * g.RowLength + 1] <- 4
So why is calling it a compile error?
Note: I am aware that this compiler error exists to make it impossible to mutate a non-mutable value of a struct by setting one of its fields. But I'm clearly not mutating the struct here.
I'm gonna take a guess here that its the second part of that error message that applies - "or take the address of a value type". Its not the mutability but the address of the value type that needs to be taken in order for you to refer to the same value g when mutating the Data.
It's probably impossible the compiler could consistently prove any setter doesn't actually mutate the struct, so it doesn't bother and just always emits the error when using assignment statements on non-mutable struct bindings.
In other words the question becomes: why does F# assume property setters mutate their instance? Well, probably because that's usually what property setters do.
Inlining the property setter works in this case because then the target of the assignment is an element of a property and not a property of the struct itself.
var tf:TextFormat = myTextField.getTextFormat();
trace(typeof tf.color); // "number"
trace(tf.color is uint); // true
var myColor:uint = tf.color; // error: 1118: Implicit coercion of a value with static type Object to a possibly unrelated type Number.
Why?
var myColor:uint = int(tf.color); // works. But why do I have to cast it?
From Adobe's API reference:
color:Object
So color is type of Object, the second line traced out number as type because it was assigned by default or in code, but it does not necessarily mean that color can only be number. We can assign string type to color object as well, so type of tf.color can be a number or a String:
tf.color = "0x00ff00";
myTextField.setTextFormat(tf); // Change text color to green
If we compare the following two lines:
var myColor:uint = "0x00ff00"; // 1067: Implicit coercion of a value of type String to an unrelated type uint.
var myColor:uint = tf.color; // 1118: Implicit coercion of a value with static type Object to a possibly unrelated type Number.
// var myColor:uint = new Object(); // This line gives same 1118: Implicit coercion of a value with static type Object to a possibly unrelated type uint.
We can see that the compiler is complaining that it needs explicit instructions to perform the conversion. From this point, we have enough reason to believe that the compiler is designed the way it is. Also notice that you can use constructor of uint or int to convert Object to number. uint and int are both derived classes of Object.
var myColor:uint = new uint(tf.color);
I hope this shed light.
According to this article:
As you might know, dynamic (as it is now called) is the stand-in type when a static type annotation is not provided.
So, what is the difference between dynamic and var? When to use?
dynamic is a type underlying all Dart objects. You shouldn't need to explicitly use it in most cases.
var is a keyword, meaning "I don't care to notate what the type is here." Dart will replace the var keyword with the initializer type, or leave it dynamic by default if there is no initializer.
Use var if you expect a variable assignment to change during its lifetime:
var msg = "Hello world.";
msg = "Hello world again.";
Use final if you expect a variable assignment to remain the same during its lifetime:
final msg = "Hello world.";
Using final (liberally) will help you catch situations where you accidentally change the assignment of a variable when you didn't mean to.
Note that there is a fine distinction between final and const when it comes to objects. final does not necessarily make the object itself immutable, whereas const does:
// can add/remove from this list, but cannot assign a new list to fruit.
final fruit = ["apple", "pear", "orange"];
fruit.add("grape");
// cannot mutate the list or assign a new list to cars.
final cars = const ["Honda", "Toyota", "Ford"];
// const requires a constant assignment, whereas final will accept both:
const names = const ["John", "Jane", "Jack"];
dynamic: can change TYPE of the variable, & can change VALUE of the variable later in code.
var: can't change TYPE of the variable, but can change VALUE of the variable later in code.
final: can't change TYPE of the variable, & can't change VALUE of the variable later in code.
dynamic v = 123; // v is of type int.
v = 456; // changing value of v from 123 to 456.
v = 'abc'; // changing type of v from int to String.
var v = 123; // v is of type int.
v = 456; // changing value of v from 123 to 456.
v = 'abc'; // ERROR: can't change type of v from int to String.
final v = 123; // v is of type int.
v = 456; // ERROR: can't change value of v from 123 to 456.
v = 'abc'; // ERROR: can't change type of v from int to String.
try this in DartPad:
void main() {
dynamic x = 'hal';
x = 123;
print(x);
var a = 'hal';
a = 123;
print(a);
}
you can change the type of x, but not a.
var, like final, is used to declare a variable. It is not a type at all.
Dart is smart enough to know the exact type in most situations. For example, the following two statements are equivalent:
String a = "abc"; // type of variable is String
var a = "abc"; // a simple and equivalent (and also recommended) way
// to declare a variable for string types
On the other hand, dynamic is a special type indicating it can be any type (aka class). For example, by casting an object to dynamic, you can invoke any method (assuming there is one).
(foo as dynamic).whatever(); //valid. compiler won't check if whatever() exists
(foo as var).whatever(); //illegal. var is not a type
var a ;
a = 123;
print(a is int);
print(a);
a = 'hal';
print(a is String);
When defined without initial value, var is dynamic
var b = 321;
print(b is int);
print(b);
//b = 'hal'; //error
print(b is String);
When defined with initial value, var is int in this case.
To clarify some of the previous answers, when you're declaring a variable as dynamic, it's type changes depending on what you assign to it. When you're declaring a var, the type is set once it's assigned something, and it cannot be changed after that.
For example, the following code:
dynamic foo = 'foo';
print('foo is ${foo.runtimeType} ($foo)');
foo = 123;
print('foo is ${foo.runtimeType} ($foo)');
will return the following result when run in DartPad:
foo is String (foo)
foo is int (123)
But the following code won't even compile:
var bar = 'bar';
print('bar is ${bar.runtimeType} ($bar)');
bar = 123; // <-- Won't compile, because bar is a String
print('bar is ${bar.runtimeType} ($bar)');
Long story short - use dynamic if you want a non-typed variable, use var when you want a typed variable with whatever type you assign to it.
Looking at the previous answers I hope this can clarify/summarize everything:
There are the keywords var, final, and const. These are to declare a variable (to indicate its existence) (Side note: Declaration vs Initialization)
Then there are types like String, int, List, dynamic, etc. (The type indicates what kind of value the variable should hold, this is for type safety)
Usually, we declare a variable by explicitly stating its type:
String a; // a is now a String type
int b; // b is now an int type
But we can also use the var keyword. By default, this sets the type of the variable to whatever it is initialized with. (This is called type inference)
var a = "hello"; // a is now a String type
var b = 5; // b is now an int type
Now what happens when you try to declare a variable with the var keyword, but don't initialize a value? How is it supposed to infer a type? Well, there is also a type called dynamic. This is different than the usual String or int in the sense that it allows for the variable to be assigned a value of any type (Usually there will be an error).
String a = "hello"; // a is now a String type
// var a = "hello"; // Alternative way; same as the line above because its type is inferred to be String
a = 5 // error: A value of type 'int' can't be assigned to a variable of type 'String'
dynamic b; // b is now a dynamic type
b = "hello"; // still a dynamic type, but now its value is of type String (You can use b.runtimeType to check)
b = 5; // dynamic type, but now its value is of type int
So to address the original confusion regarding the quote from the article,
As you might know, dynamic (as it is now called) is the stand-in type when a static type annotation is not provided.
It just means that if you don't explicitly state its type (you use var to declare a variable) and do so without initialization, it simply infers its type as dynamic:
var b; // b is now a dynamic type, the following will not have any errors.
b = "hello";
b = 5;
b = true;
Other notes:
Not sure why people started talking about final and const, but I think the accepted answer here explains it well if you want to know more.
dynamic a; and var a; is effectively the same: They both declare a variable of dynamic type.
Two ways of checking the type of a variable is using the is operator and using .runtimeType which works differently. See the following example:
dynamic b; // b is now a dynamic type, no value
print(b is dynamic); // true
print(b is Null); // true
print(b is String); // false
print(b is int); // false
print(b.runtimeType); // Null
b = "hello"; // dynamic type, String value
print(b is dynamic); // true
print(b is Null); // false
print(b is String); // true
print(b is int); // false
print(b.runtimeType); // String
b = 5; // dynamic type, int value
print(b is dynamic); // true
print(b is Null); // false
print(b is String); // false
print(b is int); // true
print(b.runtimeType); // int
One of aspect than can consider in comparison dynamic vs var is taking into account behavior when using var declaration with initialization at the same time there is not possibility to change type which in case of dynamic is.
But dynamic vs var is not the question what I would ask.
I would ask more what is difference between dynamic vs Object.
Here is a DO annotate with Object instead of dynamic to indicate any object is allowed.
It is hard to feel it at the beginning, but dynamic I would relate to generic type argument.
Both in dynamic and var,the variable can hold data of any data type, i.e., int , float,string,etc
If a variable is declared as a dynamic and if even initialised, its type can change over time.Try this code in https://dartpad.dev/
void main() {
dynamic x = 'abc';
x = 12345;
print(x);
}
If you declare variable as a var, once assigned type can not change.
void main() {
var x = 'abc';
x = 12345;
print(x);
}
The above code will result in the error stating that A value of type 'int' can't be assigned to a variable of type 'String' - line 3
BUT, if you state a var without initializing, it becomes a dynamic:
void main() {
var x ;
x = 'abc';
x=12345;
print(x);
}
A dynamic variable can change his type and a var type can't be changed.
For example :
var myVar = 'hello';
dynamic myDynamicVar = 'hello';
myVar = 123; // not possible
myDynamicVar = 123; // possible
dynamic is a data type that indicates all data types in dart
var is a variable declaration way like "final" that takes the data type of its value
If you use var you can't change the data type of the variable. But if you use dynamic you can change it freely.
for ex.
dynamic x = 12; // type: integer
x= "Hello world"; // type: string
This will work with no issues if you do the same using var instead of dynamic you will get an error since you can't change the data type because it is automatically assigned to the variable when initialized.
dynamic: can change the TYPE of the variable, & can change the VALUE of the variable later in the code.
var: can't change the TYPE of the variable, but can change the VALUE of the variable later in code