Thread overview
From D struct to C struct
Nov 17, 2013
Namespace
Nov 17, 2013
qznc
Nov 17, 2013
Namespace
Nov 18, 2013
Namespace
Nov 18, 2013
Namespace
Nov 18, 2013
qznc
Nov 18, 2013
Namespace
Nov 18, 2013
Maxim Fomin
Nov 18, 2013
Namespace
Nov 18, 2013
Maxim Fomin
November 17, 2013
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. :)
November 17, 2013
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
November 17, 2013
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);
}
----
November 18, 2013
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?
November 18, 2013
I found another approach. It avoids the GC and the Heap: A Circular Buffer:
http://dpaste.dzfl.pl/cf1e7afb

That should work.
November 18, 2013
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.
November 18, 2013
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.
November 18, 2013
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.
November 18, 2013
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?
November 18, 2013
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.