digitalmars.D - struct opCast to void* and back
- Nrgyzer (17/17) Apr 11 2010 Hello everyone,
- bearophile (24/26) Apr 11 2010 This is D2 code (yours was probably D1):
- Robert Clipsham (6/23) Apr 11 2010 Try *cast(MyStruct*). In opCast you are returning &this, which is of
- Nrgyzer (2/34) Apr 11 2010 By using *cast(MyStruct*) I get the following message: "Error: 1invalid ...
- Robert Clipsham (9/15) Apr 11 2010 I don't know how writefln() works in D1 (I presume that's what you're
- Nrgyzer (26/45) Apr 11 2010 I want to do the following:
- Robert Clipsham (3/28) Apr 11 2010 Why the need for void* everywhere? Surely you could save the effort and
- Nrgyzer (41/81) Apr 11 2010 Because I call MyClass.cb by using an other class... for example the But...
- Robert Clipsham (43/51) Apr 11 2010 By using templated classes you can remove the need for void*:
- Justin Spahr-Summers (12/25) Apr 11 2010 In this function, 'test' is allocated on the stack and therefore only
Hello everyone, how can I cast a struct to void* and back to my struct? I have the following struct: struct myStruct { char[] structName; public char[] toString() { return structName; } void* opCast() { return &this; } } myStruct test = myStruct(); // ok test.structName = "Example struct"; // ok void* temp = cast(void*) test; // ok writefln(cast(myStruct) temp); // failed Thanks for solutions & help :).
Apr 11 2010
Nrgyzer:Hello everyone,Hello, this is a question fitter for the D.learn newsgroup.how can I cast a struct to void* and back to my struct? I have the following struct:This is D2 code (yours was probably D1): import std.stdio: writeln; struct MyStruct { string structName; public string toString() { return structName; } void* opCast() { return &this; } } void main() { MyStruct test = MyStruct("Example struct"); void* temp1 = cast(void*)test; void* temp2 = &test; assert(temp1 == temp2); writeln(cast(MyStruct*)temp1); } Note that struct names are written in with their first letter uppercase. Using just a & you don't need that opCast. Bye, bearophile
Apr 11 2010
On 11/04/10 10:46, Nrgyzer wrote:Hello everyone, how can I cast a struct to void* and back to my struct? I have the following struct: struct myStruct { char[] structName; public char[] toString() { return structName; } void* opCast() { return&this; } } myStruct test = myStruct(); // ok test.structName = "Example struct"; // ok void* temp = cast(void*) test; // ok writefln(cast(myStruct) temp); // failed Thanks for solutions& help :).Try *cast(MyStruct*). In opCast you are returning &this, which is of type MyStruct* until it is implicitly cast to void*. In the writefln() you then cast it back to MyStruct*, and dereference it so you can use it. In your version you are trying to cast from a pointer to the struct to the actual struct, which is why it doesn't work.
Apr 11 2010
Robert Clipsham Wrote:On 11/04/10 10:46, Nrgyzer wrote:By using *cast(MyStruct*) I get the following message: "Error: 1invalid UTF-8 sequence"Hello everyone, how can I cast a struct to void* and back to my struct? I have the following struct: struct myStruct { char[] structName; public char[] toString() { return structName; } void* opCast() { return&this; } } myStruct test = myStruct(); // ok test.structName = "Example struct"; // ok void* temp = cast(void*) test; // ok writefln(cast(myStruct) temp); // failed Thanks for solutions& help :).Try *cast(MyStruct*). In opCast you are returning &this, which is of type MyStruct* until it is implicitly cast to void*. In the writefln() you then cast it back to MyStruct*, and dereference it so you can use it. In your version you are trying to cast from a pointer to the struct to the actual struct, which is why it doesn't work.
Apr 11 2010
On 11/04/10 12:47, Nrgyzer wrote:I don't know how writefln() works in D1 (I presume that's what you're using), but try the following: writefln( "%s", (*cast(MyStruct*)temp).toString() ); I don't have a D1/Phobos compiler available to me to test, so I don't know if that will help. You usually get that error when trying to print /use strings with invalid UTF sequences in them, which looking at your program, shouldn't be happening. If you're using code other than what you're showing that could be it.Try *cast(MyStruct*). In opCast you are returning&this, which is of type MyStruct* until it is implicitly cast to void*. In the writefln() you then cast it back to MyStruct*, and dereference it so you can use it. In your version you are trying to cast from a pointer to the struct to the actual struct, which is why it doesn't work.By using *cast(MyStruct*) I get the following message: "Error: 1invalid UTF-8 sequence"
Apr 11 2010
Robert Clipsham Wrote:On 11/04/10 12:47, Nrgyzer wrote:I want to do the following: struct MyStruct { char[] structName; public char[] toString() { return structName; } } ... class MyClass { private static void function(void*) callBack; private static void* callBackValue; ... static this() { MyStruct test = MyStruct(); test.structName = "Struct name"; callBack = &cb; callBackValue = &test; } ... public void cb(void* value) { MyStruct temp = *((cast(MyStruct*) value)); writefln(temp); } }I don't know how writefln() works in D1 (I presume that's what you're using), but try the following: writefln( "%s", (*cast(MyStruct*)temp).toString() ); I don't have a D1/Phobos compiler available to me to test, so I don't know if that will help. You usually get that error when trying to print /use strings with invalid UTF sequences in them, which looking at your program, shouldn't be happening. If you're using code other than what you're showing that could be it.Try *cast(MyStruct*). In opCast you are returning&this, which is of type MyStruct* until it is implicitly cast to void*. In the writefln() you then cast it back to MyStruct*, and dereference it so you can use it. In your version you are trying to cast from a pointer to the struct to the actual struct, which is why it doesn't work.By using *cast(MyStruct*) I get the following message: "Error: 1invalid UTF-8 sequence"
Apr 11 2010
On 11/04/10 15:41, Nrgyzer wrote:I want to do the following: struct MyStruct { char[] structName; public char[] toString() { return structName; } } ... class MyClass { private static void function(void*) callBack; private static void* callBackValue; ... static this() { MyStruct test = MyStruct(); test.structName = "Struct name"; callBack =&cb; callBackValue =&test; } ... public void cb(void* value) { MyStruct temp = *((cast(MyStruct*) value)); writefln(temp); } }Why the need for void* everywhere? Surely you could save the effort and store it as a MyStruct?
Apr 11 2010
Robert Clipsham Wrote:On 11/04/10 15:41, Nrgyzer wrote:Because I call MyClass.cb by using an other class... for example the Button-Class. struct MyStruct { char[] structName; public char[] toString() { return structName; } } ... class MyClass { public static Button[] loadButtons() { Button[] buttons; for (int i=0; i < 10; i++) { MyStruct curStruct = MyStruct(); curStruct.structName = .toString(i); buttons ~= new Button(cb, curStruct); } return buttons; } public static void cb(void* value) { MyStruct temp = *((cast(MyStruct*) value)); writefln(temp); } } class Button { private static void function(void*) callBack; private static void* callBackValue; this(void function(void*) cB, void* cbValue) { callBack = cB; callBackValue = cbValue; } public void pressButton() { // This should call MyClass.cb callBack(callBackValue); } } For example... I click on a button on my OpenGL-gui, then I simply call the pressButton-method in my class Button which should call MyClass.cb with callBackValue which can be a value, class, struct or a similar datatype. To store different values/classes/structs... I cast all to a void-pointer. In this case I can use the Button-class in multiple situations.I want to do the following: struct MyStruct { char[] structName; public char[] toString() { return structName; } } ... class MyClass { private static void function(void*) callBack; private static void* callBackValue; ... static this() { MyStruct test = MyStruct(); test.structName = "Struct name"; callBack =&cb; callBackValue =&test; } ... public void cb(void* value) { MyStruct temp = *((cast(MyStruct*) value)); writefln(temp); } }Why the need for void* everywhere? Surely you could save the effort and store it as a MyStruct?
Apr 11 2010
On 11/04/10 16:02, Nrgyzer wrote:Because I call MyClass.cb by using an other class... for example the Button-Class.....For example... I click on a button on my OpenGL-gui, then I simply call the pressButton-method in my class Button which should call MyClass.cb with callBackValue which can be a value, class, struct or a similar datatype. To store different values/classes/structs... I cast all to a void-pointer. In this case I can use the Button-class in multiple situations.By using templated classes you can remove the need for void*: ---- struct MyStruct { char[] structName; public char[] toString() { return structName; } } class MyClass { public static Button!(MyStruct)[] loadButtons() { Button!(MyStruct)[] buttons; for (int i=0; i< 10; i++) { MyStruct curStruct = MyStruct(); curStruct.structName = .toString(i); buttons ~= new Button!(MyStruct)(cb, curStruct); } return buttons; } public static void cb(MyStruct value) { writefln(value); } } class Button(T) { private static void function(T) callBack; private static T callBackValue; this(void function(T) cB, T cbValue) { callBack = cB; callBackValue = cbValue; } public void pressButton() { // This should call MyClass.cb callBack(callBackValue); } } ---- Of course this is more restrictive in some cases, such as if you wanted an array of buttons with different types for their callback and callbackValue, and it also adds template bloat if you have a lot of different types for buttons. There should be a way around this, I can't think of it off the top of my head though, perhaps someone else can.
Apr 11 2010
Robert Clipsham Wrote:On 11/04/10 16:02, Nrgyzer wrote:Yeah, that's a solution I didn't think about :). Thanks...Because I call MyClass.cb by using an other class... for example the Button-Class.....For example... I click on a button on my OpenGL-gui, then I simply call the pressButton-method in my class Button which should call MyClass.cb with callBackValue which can be a value, class, struct or a similar datatype. To store different values/classes/structs... I cast all to a void-pointer. In this case I can use the Button-class in multiple situations.By using templated classes you can remove the need for void*: ---- struct MyStruct { char[] structName; public char[] toString() { return structName; } } class MyClass { public static Button!(MyStruct)[] loadButtons() { Button!(MyStruct)[] buttons; for (int i=0; i< 10; i++) { MyStruct curStruct = MyStruct(); curStruct.structName = .toString(i); buttons ~= new Button!(MyStruct)(cb, curStruct); } return buttons; } public static void cb(MyStruct value) { writefln(value); } } class Button(T) { private static void function(T) callBack; private static T callBackValue; this(void function(T) cB, T cbValue) { callBack = cB; callBackValue = cbValue; } public void pressButton() { // This should call MyClass.cb callBack(callBackValue); } } ---- Of course this is more restrictive in some cases, such as if you wanted an array of buttons with different types for their callback and callbackValue, and it also adds template bloat if you have a lot of different types for buttons. There should be a way around this, I can't think of it off the top of my head though, perhaps someone else can.
Apr 11 2010
Robert Clipsham Wrote:On 11/04/10 16:02, Nrgyzer wrote:I tried a bit with templates and classes - without success. I always get the following error: "Error: template instance Button!(myStruct) forward references template declaration Button(T)" when I try to create a Button array like this one: private Button!(T)[]; That's exactly the same error message which was posted on http://www.digitalmars.com/d/archives/digitalmars/D/bugs/Issue_3834_New_forward_reference_in_templated_class_21207.htmlBecause I call MyClass.cb by using an other class... for example the Button-Class.....For example... I click on a button on my OpenGL-gui, then I simply call the pressButton-method in my class Button which should call MyClass.cb with callBackValue which can be a value, class, struct or a similar datatype. To store different values/classes/structs... I cast all to a void-pointer. In this case I can use the Button-class in multiple situations.By using templated classes you can remove the need for void*: ---- struct MyStruct { char[] structName; public char[] toString() { return structName; } } class MyClass { public static Button!(MyStruct)[] loadButtons() { Button!(MyStruct)[] buttons; for (int i=0; i< 10; i++) { MyStruct curStruct = MyStruct(); curStruct.structName = .toString(i); buttons ~= new Button!(MyStruct)(cb, curStruct); } return buttons; } public static void cb(MyStruct value) { writefln(value); } } class Button(T) { private static void function(T) callBack; private static T callBackValue; this(void function(T) cB, T cbValue) { callBack = cB; callBackValue = cbValue; } public void pressButton() { // This should call MyClass.cb callBack(callBackValue); } } ---- Of course this is more restrictive in some cases, such as if you wanted an array of buttons with different types for their callback and callbackValue, and it also adds template bloat if you have a lot of different types for buttons. There should be a way around this, I can't think of it off the top of my head though, perhaps someone else can.
Apr 11 2010
On Sun, 11 Apr 2010 10:41:29 -0400, Nrgyzer <nrgyzer gmail.com> wrote:... class MyClass { private static void function(void*) callBack; private static void* callBackValue; ... static this() { MyStruct test = MyStruct(); test.structName = "Struct name"; callBack = &cb; callBackValue = &test; }In this function, 'test' is allocated on the stack and therefore only exists for the duration of the function call. When the static constructor finishes, any pointers directed at 'test' are basically garbage and should never be used. There are three workarounds: 1. Store 'test' in a place where it won't get destructed until you're done using it. 2. Allocate 'test' on the heap by using a pointer and 'new'. 3. Change MyStruct into a class so objects are allocated on the heap by default. This is probably the best solution for situations like this, especially given your explanation of what you're trying to do.
Apr 11 2010