I have this struct:
struct foo {
int a;
union {
struct {
int b;
struct bar
{
int c;
int d;
} *aBar;
} in;
} u;
};
How I need to declare a variable of type bar, in Visual C++ ?
When you declare an structure like this:
struct
{
int b;
} in;
You are actually creating an object with name in, having unnamed-data type. This data-type would be named internally by compiler, and depends on compiler. The style given above does not declare in to be a type, but a variable!
If you want to make it a type, use either of given approaches:
// Approach 1
struct in{...};
// Approach 2
typedef struct {..} in; // in is now a type, because of `typedef`
If you have compiler that supports C++0x, and specifically type decltype keyword, you can use it against the first style (which makes in a variable). Example:
decltype(in) in_var;
in_var.b = 10;
Thanks Ajay, I solved that way:
foo *k;
decltype(k->u.in.aBar) j;
j->c = 1;
j->d = 1;
Related
I created a struct with a reference to a vector and I'm having problems assigning to it after I created an array of structs.
This is my struct:
struct name{
std::vector<Student> &A;
int a;
int b;
};
In my main, I have created a vector of class type, Student, and I have assigned values to the vector, which I called StudentVector. I'm trying to declare an array of struct name that contains a reference to my vector, StudentVector:
void main(){
std::vector <Student> StudentVector;
....
....
....
name data[5];
for (int i=0;i<5;i++){
data[i].A = StudentVector;
}
When I do this, it compiles, but I get a segmentation fault when I run my code.
Thank you in advance for the help!
It should not compile, because there is no way how to initialize the reference 'A'. If you really need to do it this way, replace the reference with a pointer:
struct name {
std::vector<Student> *A;
int a;
int b;
};
std::vector<Student> StudentVector;
for (int i = 0; i < 5; i++) {
data[i].A = &StudentVector;
}
But it would be wise to avoid it completely.
I'm trying to make some structs that are dependant on each other in Lua like so. But I'm having problems doing it. Is there anyway I can predefine Foo as an empty struct and define it afterwards?
Thanks.
ffi.cdef[[
typedef struct {
Foo* foo;
} Bar;
]]
ffi.cdef[[
typedef struct {
Bar* bar;
} Foo;
]]
This is not a problem specific of LuaJIT and the FFI but how to declare interdependent data structures and functions in C.
C requires that a function has been defined before using it. For instance:
int foo() {
bar();
}
int bar() {
return 42;
}
To solve this issue is necessary to declare function bar() at the beginning of the file. The behavior of the function can be defined later.
int bar();
int foo() {
bar();
}
int bar() {
return 42;
}
Similarly, you need to declare Foo before using it in Bar. Also notice it's possible to put all the C definitions in the same block.
ffi.cdef[[
typedef struct Foo Foo;
typedef struct {
Foo* Foo;
} Bar;
typedef struct {
Bar* bar;
} Foo;
]]
struct Data {
public int x;
}
void change_x(Data data) {
data.x = 123;
}
Data a = Data();
change_x(a);
print("%d", a.x); // 0
but the document says:
when a struct type instance is passed to a method, a copy is not made. Instead a reference to the instance is passed.
- in https://wiki.gnome.org/Projects/Vala/Manual/Types
What is wrong?
Structs in Vala are implemented as copy on assignment and pass by reference. So you can think of your example as copying the struct because it is being assigned to a parameter in a function and then that copy is passed by reference. This is what is happening behind the scenes in the generated C code, but from the Vala side it means a struct is a value type. Only when interfacing with a C library is it useful to know a copy of the struct is passed by reference. The quote from the manual refers to struct methods, but before we look at that in detail let's understand a bit more about value and reference types.
Vala, like Java, C# and many other languages, has two kinds of data types: value types and reference types.
Value Types are Passed by Value
When a value type is passed as an argument to a function or a method then the value is passed as the argument, but it is a copy of the value. If the function or method goes on to modify the parameter it received this will not change the value in the calling code. The code is encapsulated.
The following example:
void main () {
int a = 23;
print ("Initial value: %i\n", a);
modify_example (a);
print ("Final value: %i\n", a);
}
void modify_example (int x) {
x += 100;
}
produces:
Initial value: 23
Final value: 23
Although the value is modified in the function it does not also modify the value from the calling code.
Value Types Can be Passed by Reference
Instead of passing the value to a function or a method the use of the ref keyword will pass a reference to the value. This creates an alias for the calling value. The result is two identifiers for the same memory location.
By just adding the ref keyword the following example:
void main () {
int a = 23;
print ("Initial value: %i\n", a);
modify_example (ref a);
print ("Final value: %i\n", a);
}
void modify_example (ref int x) {
x += 100;
}
now produces:
Initial value: 23
Final value: 123
By calling modify_example () the side effect is to also change the value in the calling code. The use of ref makes this explicit and can be used as a way for a function to return multiple values, but in this example it would be clearer to return the modified value instead of passing by reference.
Reference Types are Always Passed by Reference
Objects are reference types. This example doesn't use an explicit ref, but the value is changed in the calling code:
void main () {
var a = new ExampleReferenceType (23);
print ("Initial value: %i\n", a.value);
modify_example (a);
print ("Final value: %i\n", a.value);
}
class ExampleReferenceType {
public int value;
public ExampleReferenceType (int default = 0) {
this.value = default;
}
}
void modify_example (ExampleReferenceType x) {
x.value += 100;
}
This produces:
Initial value: 23
Final value: 123
Objects modified in this way can cause problems when tracking down a bug. That is an advantages of making value objects immutable. This would be done by only setting the value in the constructor, making all fields private and only using a property to get the value, but not set it.
Structs as Value Types
The following code:
void main () {
ExampleStruct a = { 23 };
print ("Initial value: %i\n", a.value);
modify_example (a);
print ("Final value: %i\n", a.value);
}
private struct ExampleStruct {
public int value;
}
void modify_example (ExampleStruct x) {
x.value += 100;
}
is similar to your code and produces:
Initial value: 23
Final value: 23
This is the same behaviour in Vala as the other value types, but if you look at the C code by using the --ccode switch with valac you will see the struct is copied and passed by reference. This is relevant when you need to understand how Vala maintains the C ABI (Application Binary Interface).
Struct Methods
The reference you make to the manual may not be clear, but I think it relates to methods within structs. If modify_example is moved inside the struct definition:
void main () {
ExampleStruct a = { 23 };
print ("Initial value: %i\n", a.value);
a.modify_example ();
print ("Final value: %i\n", a.value);
}
private struct ExampleStruct {
public int value;
public void modify_example () {
this.value += 100;
}
}
this now produces:
Initial value: 23
Final value: 123
The method now operates on the instance.
[SimpleType] Structs
The section from the manual you quote also states in the next sentence:
This behaviour can be changed by declaring the struct to be a simple
type.
So for completeness here is the final example:
void main () {
ExampleStruct a = { 23 };
print ("Initial value: %i\n", a.value);
a.modify_example ();
print ("Final value: %i\n", a.value);
}
[SimpleType]
private struct ExampleStruct {
public int value;
public void modify_example () {
this.value += 100;
}
}
and this produces:
Initial value: 23
Final value: 23
Although the method is still defined within the struct the instance is passed by value instead of reference.
Simple type structs are how the fundamental value types are defined in Vala, for example int and int64. If you want a struct method defined that acts on a simple type struct instance then the method will have to be defined to return a new instance containing the modified value.
Conclusion
Structs are value types in Vala, but it is useful to know how they are implemented to understand compatibility with the C ABI. In your example the struct behaves as a value type, but is copied and passed by reference in terms of the C ABI. The quote seems most relevant to methods defined within structs.
I think the quoted text you are refering to is either outdated or was wrong to begin with.
You have to use ref (or out) if you want it to be passed by reference (hence the name ref).
struct Data {
public int x;
}
void change_x (ref Data data) {
data.x = 123;
}
int main () {
Data a = Data ();
change_x (ref a);
print ("%d\n", a.x);
return 0;
}
How can I create a garbage-collected copy of a struct that's on the stack?
Coming from a C++ background, my first guess would be a copy constructor like the one below, but it doesn't seem very idiomatic for D, and I haven't seen one in any of the D projects I've taken a look at.
struct Foo {
immutable int bar;
this(int b) { bar = b; }
// A C++-style copy constructor works but doesn't seem idiomatic.
this(ref const Foo f) { bar = f.bar; }
}
void main()
{
// We initialize a Foo on the stack
auto f = Foo(42);
// Now I want to get a heap copy of its member. How?
// A C++-style copy constructor works but doesn't seem idiomatic.
Foo* f1 = new Foo(f);
}
Your example is overly complicated and doesn't even compile, but essentially, it sounds like what you want to be able to do is something like
struct Foo
{
int i;
}
void main()
{
auto f = Foo(5);
auto g = new Foo(f);
}
What you can do without any special constructors is
void main()
{
auto f = Foo(5);
auto g = new Foo;
*g = f;
}
but obviously that's more steps than you probably want. The normal "copy constructor" for D is a postblit constructor, which is declared as this(this) {...}, but that's not required for Foo as it's declared here (since all of its members are value types), and it doesn't help with allocating a struct on the heap anyway - just with copying a struct. Arguably
auto f = Foo(5);
auto g = new Foo(f);
should just work, but at the moment, it doesn't, and there is unfortunately, no support in the language for defining it for you. So, unfortunately, I think that you're currently forced to do something akin to what you're trying to avoid. e.g.
struct Foo
{
int i;
this(int j)
{
i = j;
}
this(Foo rhs)
{
this = rhs;
}
}
void main()
{
auto f = Foo(5);
auto g = new Foo(f);
}
However, I just opened an enhancement request for making it so that new Foo(foo) will just work, and with the next release of dmd (2.066) we're going to get universal construction for primitive types (e.g. new int(5) will now work), so I think that there's a very good argument for this just working as well.
For now though, you're going to have to provide an extra constructor to get this to work.
[s].ptr will copy the struct s to the heap, and get a pointer to it.
I'm having problems passing a structure of vectors to an OpenCL kernel.
Long story short, I have found that I CAN pass a C structure:
typedef struct {
cl_float4 vec;
} my_type;
. . . to a kernel, if I declare it like:
typedef struct { float s[4]; } my_float4;
typedef struct { my_float4 vec; } my_type; //use custom float4
__kernel void function(const my_type test) {}
. . . but NOT, if I declare it like:
typedef struct { float4 vec; } my_type; //use built-in float4
__kernel void function(const my_type test) {}
So my question is, what makes a float4 different and special? In the second example, I get CL_INVALID_ARG_SIZE on clSetKernelArg. In the host code, I'm using cl_float4--isn't that supposed to be paired with float4 in the kernel?
EDIT: by request, the clSetKernelArg code (error handling cropped):
template <typename type_data> void set_argument(int arg_index, const type_data* data) {
cl_int err = clSetKernelArg(kernel,arg_index,sizeof(type_data),data);
if (err!=CL_SUCCESS) throw "ERROR"; /*simplified*/
}
I call the function with a struct declared exactly as above:
my_type test;
my_kernel->set_argument(0,&test);
This sounds like a bug with your implementation - you should be able to pass that user-defined type to a kernel without issue. What platform / SDK are you using? I was able to successfully declare this type in host code:
typedef struct _mytype {
cl_float4 val;
} mytype;
... and then later use it:
mytype t;
status = clSetKernelArg(kernel, argc++, sizeof(mytype), &t);
check_status("clSetKernelArg:mytype t", status);
Where check_status does what you'd expect: checks for a non-CL_SUCCESS return value.
The kernel looks like this:
typedef struct _mytype {
float4 value;
} mytype;
kernel void do_it(/* ... */, const mytype test) { /* ... */ }
This compiles and executes, giving correct results on the CPU device.