www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - From D struct to C struct

reply "Namespace" <rswhite4 googlemail.com> writes:
Hello.
I have some trouble with C interfacing.
I have a C struct with an integer member and I want to wrap this 
into a D template. But if I want to access the C API, I have to 
convert the C struct with the type informations of the D struct.
Example: http://dpaste.dzfl.pl/e3d10755

The question is: How can I write the ptr method? It is very 
probable, that these conversion is often used, so the ptr method 
should be fast and without many garbage. And If possible, I want 
to avoid the GC / Heap.
My current approach doesn't avoid the GC complete, but it 
displace the problem: http://dpaste.dzfl.pl/449f663f

Any further ideas how to solve that?

And yes I want to solve the whole conversion in the ptr method 
and don't want to write something like that all the time:
----
void foo(ref const Df df) {
     C c = C(cast(int) df.id);
     c_method(&c);
}
----

or

----
void foo(ref const Df df) {
     C c = df.asC();
     c_method(&c);
}
----

Thanks in advance. :)
Nov 17 2013
parent reply "qznc" <qznc web.de> writes:
On Sunday, 17 November 2013 at 22:11:02 UTC, Namespace wrote:
 Hello.
 I have some trouble with C interfacing.
 I have a C struct with an integer member and I want to wrap 
 this into a D template. But if I want to access the C API, I 
 have to convert the C struct with the type informations of the 
 D struct.
 Example: http://dpaste.dzfl.pl/e3d10755

 The question is: How can I write the ptr method? It is very 
 probable, that these conversion is often used, so the ptr 
 method should be fast and without many garbage. And If 
 possible, I want to avoid the GC / Heap.
 My current approach doesn't avoid the GC complete, but it 
 displace the problem: http://dpaste.dzfl.pl/449f663f

 Any further ideas how to solve that?
You cannot use the stack due to your API requirements, so only heap or data segment remains. I assume you cannot use static variables, so heap it is. You should look into Andreis proposed std.allocator to optimize your memory management. http://forum.dlang.org/post/l4btsk$5u8$1 digitalmars.com
Nov 17 2013
next sibling parent "Namespace" <rswhite4 googlemail.com> writes:
On Sunday, 17 November 2013 at 22:25:54 UTC, qznc wrote:
 On Sunday, 17 November 2013 at 22:11:02 UTC, Namespace wrote:
 Hello.
 I have some trouble with C interfacing.
 I have a C struct with an integer member and I want to wrap 
 this into a D template. But if I want to access the C API, I 
 have to convert the C struct with the type informations of the 
 D struct.
 Example: http://dpaste.dzfl.pl/e3d10755

 The question is: How can I write the ptr method? It is very 
 probable, that these conversion is often used, so the ptr 
 method should be fast and without many garbage. And If 
 possible, I want to avoid the GC / Heap.
 My current approach doesn't avoid the GC complete, but it 
 displace the problem: http://dpaste.dzfl.pl/449f663f

 Any further ideas how to solve that?
You cannot use the stack due to your API requirements, so only heap or data segment remains. I assume you cannot use static variables, so heap it is. You should look into Andreis proposed std.allocator to optimize your memory management. http://forum.dlang.org/post/l4btsk$5u8$1 digitalmars.com
I use my own allocators until Andreis are official merged into phobos. But I hoped to avoid the Heap. I found one solution which would work without using the heap, but I'm unsure how good and safe it is: ---- import std.stdio; struct C { int id; } struct C2 { C _c = void; inout(C*) ptr() inout pure nothrow { return &this._c; } } struct D(T) { T id = 0; C2 asC2() const { return C2(C(cast(int) this.id)); } /// Lots of more comfortable methods. } void stuff(const C* a, C* b) { writefln("a id = %d", a.id); writefln("b id = %d", b.id); } alias Df = D!float; void main() { Df src; Df dst; stuff(src.asC2().ptr, dst.asC2().ptr); } ----
Nov 17 2013
prev sibling parent reply "Namespace" <rswhite4 googlemail.com> writes:
On Sunday, 17 November 2013 at 22:25:54 UTC, qznc wrote:
 On Sunday, 17 November 2013 at 22:11:02 UTC, Namespace wrote:
 Hello.
 I have some trouble with C interfacing.
 I have a C struct with an integer member and I want to wrap 
 this into a D template. But if I want to access the C API, I 
 have to convert the C struct with the type informations of the 
 D struct.
 Example: http://dpaste.dzfl.pl/e3d10755

 The question is: How can I write the ptr method? It is very 
 probable, that these conversion is often used, so the ptr 
 method should be fast and without many garbage. And If 
 possible, I want to avoid the GC / Heap.
 My current approach doesn't avoid the GC complete, but it 
 displace the problem: http://dpaste.dzfl.pl/449f663f

 Any further ideas how to solve that?
You cannot use the stack due to your API requirements, so only heap or data segment remains. I assume you cannot use static variables, so heap it is. You should look into Andreis proposed std.allocator to optimize your memory management. http://forum.dlang.org/post/l4btsk$5u8$1 digitalmars.com
That reminds me: Even if I use the Heap, I cannot deal with a const ptr method (because I must update the pointer), but sometimes I have to. Therefore it isn't possible to declare a C pointer inside of D. So AFAIK there are only those two ways of me. Or did I miss something?
Nov 17 2013
parent reply "Namespace" <rswhite4 googlemail.com> writes:
I found another approach. It avoids the GC and the Heap: A 
Circular Buffer:
http://dpaste.dzfl.pl/cf1e7afb

That should work.
Nov 18 2013
parent reply "qznc" <qznc web.de> writes:
On Monday, 18 November 2013 at 08:32:11 UTC, Namespace wrote:
 I found another approach. It avoids the GC and the Heap: A 
 Circular Buffer:
 http://dpaste.dzfl.pl/cf1e7afb

 That should work.
It is unsafe, but might work in your specific case. The problem is that future changes might exhibit memory corruption, if the limit of your buffer is too low. Would probably be a hell to debug.
Nov 18 2013
parent reply "Namespace" <rswhite4 googlemail.com> writes:
On Monday, 18 November 2013 at 10:09:12 UTC, qznc wrote:
 On Monday, 18 November 2013 at 08:32:11 UTC, Namespace wrote:
 I found another approach. It avoids the GC and the Heap: A 
 Circular Buffer:
 http://dpaste.dzfl.pl/cf1e7afb

 That should work.
It is unsafe, but might work in your specific case. The problem is that future changes might exhibit memory corruption, if the limit of your buffer is too low. Would probably be a hell to debug.
Yes, but I know I never need more than 4 C pointer at the same time.
Nov 18 2013
parent reply "Maxim Fomin" <maxim maxim-fomin.ru> writes:
On Monday, 18 November 2013 at 14:15:02 UTC, Namespace wrote:
 On Monday, 18 November 2013 at 10:09:12 UTC, qznc wrote:
 On Monday, 18 November 2013 at 08:32:11 UTC, Namespace wrote:
 I found another approach. It avoids the GC and the Heap: A 
 Circular Buffer:
 http://dpaste.dzfl.pl/cf1e7afb

 That should work.
It is unsafe, but might work in your specific case. The problem is that future changes might exhibit memory corruption, if the limit of your buffer is too low. Would probably be a hell to debug.
Yes, but I know I never need more than 4 C pointer at the same time.
I think there is bigger problem (and bigger memory error) here. When you inside struct method load pointer to some field you cannot rely that after leaving the method, the pointer will be safe. Structs are almost often located in stack and there are movable, which means that struct stack 'this' pointer may change. There is even issue in bugzilla with example when delegate touches struct field and is invoked at some point later which causes silent memory error because delegate pointer became invalid.
Nov 18 2013
parent reply "Namespace" <rswhite4 googlemail.com> writes:
On Monday, 18 November 2013 at 15:27:46 UTC, Maxim Fomin wrote:
 On Monday, 18 November 2013 at 14:15:02 UTC, Namespace wrote:
 On Monday, 18 November 2013 at 10:09:12 UTC, qznc wrote:
 On Monday, 18 November 2013 at 08:32:11 UTC, Namespace wrote:
 I found another approach. It avoids the GC and the Heap: A 
 Circular Buffer:
 http://dpaste.dzfl.pl/cf1e7afb

 That should work.
It is unsafe, but might work in your specific case. The problem is that future changes might exhibit memory corruption, if the limit of your buffer is too low. Would probably be a hell to debug.
Yes, but I know I never need more than 4 C pointer at the same time.
I think there is bigger problem (and bigger memory error) here. When you inside struct method load pointer to some field you cannot rely that after leaving the method, the pointer will be safe. Structs are almost often located in stack and there are movable, which means that struct stack 'this' pointer may change. There is even issue in bugzilla with example when delegate touches struct field and is invoked at some point later which causes silent memory error because delegate pointer became invalid.
So I should change it from C[8] to C[] = new C[8]; to be sure?
Nov 18 2013
parent "Maxim Fomin" <maxim maxim-fomin.ru> writes:
On Monday, 18 November 2013 at 16:03:33 UTC, Namespace wrote:
 On Monday, 18 November 2013 at 15:27:46 UTC, Maxim Fomin wrote:
 I think there is bigger problem (and bigger memory error) 
 here. When you inside struct method load pointer to some field 
 you cannot rely that after leaving the method, the pointer 
 will be safe. Structs are almost often located in stack and 
 there are movable, which means that struct stack 'this' 
 pointer may change.

 There is even issue in bugzilla with example when delegate 
 touches struct field and is invoked at some point later which 
 causes silent memory error because delegate pointer became 
 invalid.
So I should change it from C[8] to C[] = new C[8]; to be sure?
Yes.
Nov 18 2013