digitalmars.D.learn - delegates with C linkage
- Zarathustra (24/24) Jun 04 2010 I have obtained a strange error message when I tried to use delegate as ...
- Mike Parker (12/40) Jun 04 2010 For starters, your first delegate is declared in an extern(C) block,
- Simen kjaeraas (10/13) Jun 05 2010 If this is correct, the problem should be fixable by writing
- Zarathustra (3/14) Jun 05 2010 I expecting nothing :) I use it only to highlight that it is not a membe...
- dennis luehring (5/10) Jun 05 2010 only with static methods - a real delegate needs the this-pointer in a
- Zarathustra (3/7) Jun 05 2010 gcc:
- dennis luehring (2/9) Jun 05 2010 ok so your using gcc and some "extensions"
- dennis luehring (6/17) Jun 05 2010 but that will help on the caller side (you using gcc?) but D still won't...
- Zarathustra (97/102) Jun 05 2010 I haven't shown the code before for two reasons. The first one is that t...
- Simen kjaeraas (9/11) Jun 06 2010 Nor do classes, and those certainly can be passed to a C-linkage
- dennis luehring (10/14) Jun 06 2010 my fault - yes its possible to use delegates in non D but delegat-struct...
- Zarathustra (17/26) Jun 06 2010 It would be great, if the DMC will provide such extensions like the dthi...
- bearophile (4/8) Jun 06 2010 I have asked for something similar. In such explanations I'd even like s...
- dennis luehring (4/13) Jun 06 2010 ok and it would be nice to have an clear description of this ABI+disasm
- Don (5/12) Jun 07 2010 Yes, but I think that's a bug too. Quite a horrible one, in fact, since
I have obtained a strange error message when I tried to use delegate as an argument in a C linkage function. private extern (C) static { void d_foo_add_event_handler(Foo, void delegate()); } class Foo { void addEventHandler(void delegate() handler) { d_foo_add_event_handler(this, handler); } } //__________________________________________________________________________ Error: function foo.d_foo_add_event_handler(Foo, void delegate()) does not match parameter types (Foo, void delegate()) Error: cannot implicitly convert expression (handler) of type void delegate() to void delegate() The second error message is especially extreme. When I use: struct DelegateVoid { void* ptr, funcptr; } // void delegate() ABI ... void d_foo_add_event_handler(Foo, DelegateVoid); ... d_foo_add_event_handler(this, *cast(DelegateVoid*)&handler); Everything works well but I still have no idea why I cannot implicitly use delegates.
Jun 04 2010
Zarathustra wrote:I have obtained a strange error message when I tried to use delegate as an argument in a C linkage function. private extern (C) static { void d_foo_add_event_handler(Foo, void delegate()); } class Foo { void addEventHandler(void delegate() handler) { d_foo_add_event_handler(this, handler); } } //__________________________________________________________________________ Error: function foo.d_foo_add_event_handler(Foo, void delegate()) does not match parameter types (Foo, void delegate()) Error: cannot implicitly convert expression (handler) of type void delegate() to void delegate() The second error message is especially extreme. When I use: struct DelegateVoid { void* ptr, funcptr; } // void delegate() ABI ... void d_foo_add_event_handler(Foo, DelegateVoid); ... d_foo_add_event_handler(this, *cast(DelegateVoid*)&handler); Everything works well but I still have no idea why I cannot implicitly use delegates.For starters, your first delegate is declared in an extern(C) block, meaning it has C linkage. The second is declared outside of the block, meaning it has D linkage. So they are two different types of delegates. Secondly, I'm not sure if you can pass delegates to a C function. C code wouldn't understand delegates. They are not the same as function pointers. I suggest you use function pointers instead, paying attention to linkage. On an unrelated note, what are you expecting the static keyword to do in your function declaration? It does not restrict function visibility to module scope, as it does in C and C++. That's what private is for. Here, static is meaningless.
Jun 04 2010
Mike Parker <aldacron gmail.com> wrote:For starters, your first delegate is declared in an extern(C) block, meaning it has C linkage. The second is declared outside of the block, meaning it has D linkage. So they are two different types of delegates.If this is correct, the problem should be fixable by writing extern(C) void d_foo_add_event_handler(Foo, void delegate()); or (not entirely sure about this one) alias void delegate() voidDelegate; extern(C) { void d_foo_add_event_handler(Foo, voidDelegate); } -- Simen
Jun 05 2010
For starters, your first delegate is declared in an extern(C) block, meaning it has C linkage. The second is declared outside of the block, meaning it has D linkage. So they are two different types of delegates.What is the difference?Secondly, I'm not sure if you can pass delegates to a C function. C code wouldn't understand delegates. They are not the same as function pointers. I suggest you use function pointers instead, paying attention to linkage.Of course It is possible, because I have done it and it works pretty well.On an unrelated note, what are you expecting the static keyword to do in your function declaration? It does not restrict function visibility to module scope, as it does in C and C++. That's what private is for. Here, static is meaningless.I expecting nothing :) I use it only to highlight that it is not a member function.
Jun 05 2010
Am 05.06.2010 13:33, schrieb Zarathustra:only with static methods - a real delegate needs the this-pointer in a register (not on the stack), thats the main difference between function ptr and delegates, thats why you can't use a (non static) method on for example the win-api callbacks, because the caller don't know your objectSecondly, I'm not sure if you can pass delegates to a C function. C code wouldn't understand delegates. They are not the same as function pointers. I suggest you use function pointers instead, paying attention to linkage.Of course It is possible, because I have done it and it works pretty well.
Jun 05 2010
only with static methods - a real delegate needs the this-pointer in a register (not on the stack), thats the main difference between function ptr and delegates, thats why you can't use a (non static) method on for example the win-api callbacks, because the caller don't know your objectgcc: __attribute__((regparm (1))) put_first_paramerter_to_eax(d_object this){...} __attribute__((regparm (1))) - puts the first function parameter to EAX.
Jun 05 2010
Am 05.06.2010 15:42, schrieb Zarathustra:ok so your using gcc and some "extensions"only with static methods - a real delegate needs the this-pointer in a register (not on the stack), thats the main difference between function ptr and delegates, thats why you can't use a (non static) method on for example the win-api callbacks, because the caller don't know your objectgcc: __attribute__((regparm (1))) put_first_paramerter_to_eax(d_object this){...} __attribute__((regparm (1))) - puts the first function parameter to EAX.
Jun 05 2010
Am 05.06.2010 16:03, schrieb dennis luehring:Am 05.06.2010 15:42, schrieb Zarathustra:but that will help on the caller side (you using gcc?) but D still won't accept an delegat in an extern C because this type does not exists in the C world btw: can show us code where you do this and it works - why don't you use your working code as an example?ok so your using gcc and some "extensions"only with static methods - a real delegate needs the this-pointer in a register (not on the stack), thats the main difference between function ptr and delegates, thats why you can't use a (non static) method on for example the win-api callbacks, because the caller don't know your objectgcc: __attribute__((regparm (1))) put_first_paramerter_to_eax(d_object this){...} __attribute__((regparm (1))) - puts the first function parameter to EAX.
Jun 05 2010
but that will help on the caller side (you using gcc?) but D still won't accept an delegat in an extern C because this type does not exists in the C worldMaybe it is the reason but the error message is still nonsense.btw: can show us code where you do this and it works - why don't you use your working code as an example?I haven't shown the code before for two reasons. The first one is that the my project is big and the second one is that the possibility of doing that haven't been a part of my question. If you want to know how to do that look at the examples. (1) Look at the following (probably most simple) example of d thiscall under c: /* * test.c; */ #define d_foo_get_add _D4test3Foo6getAddMFiZi #include <stdio.h> typedef struct { void* vptr ; /* unused */ void* monitor; /* unused */ int a; } st_d_foo, *DFoo; __attribute__((regparm(1), stdcall)) int d_foo_get_add(DFoo this, int o_addme) { return this->a += o_addme; } ______________________________________________________________________________ /* * test.d */ module test; static import std.stdio; public class Foo { private int a; public int getAdd(int); } void main() { Foo foo = new Foo(); foo.a = 5; std.stdio.writefln("foo.a = %d", foo.getAdd(4)); } ______________________________________________________________________________ /* command line: */ gcc test.c -c -otest.c.o dmd test.d -c -oftest.d.o dmd test.d.o test.c.o -oftest ______________________________________________________________________________ /* output is of course*/ foo.a = 9 ______________________________________________________________________________ (2) And now lets add delegate: /* * test.c; */ #define d_foo_get_var _D4test3Foo6getAddMFiZi #define d_foo_dlg _D4test3Foo3dlgMFDFZiZv #define call_delegate(x) (x).funcptr((x).ptr) #include <stdio.h> typedef struct { void* vptr ; /* unused */ void* monitor; /* unused */ int a; } st_d_foo, *DFoo; typedef struct { void* ptr; int (__attribute__((regparm(1), stdcall)) * funcptr)(void*); } st_d_delegate; __attribute__((regparm(1), stdcall)) int d_foo_get_var(DFoo this, int o_addme) { return this->a += o_addme; } __attribute__((regparm(1), stdcall)) void d_foo_dlg(DFoo this, st_d_delegate o_handler) { printf("dlg = %d\n", call_delegate(o_handler)); } ______________________________________________________________________________ /* * test.d */ module test; static import std.stdio; public class Foo { private int a; public int getAdd(int); public void dlg(int delegate()); } public class Bar { int get7() { return 7; } } void main() { Foo foo = new Foo(); foo.a = 5; std.stdio.writefln("foo.a = %d", foo.getAdd(4)); Bar bar = new Bar(); foo.dlg(&bar.get7); } ______________________________________________________________________________ command line is the same ______________________________________________________________________________ /* output */ foo.a = 9 dlg = 7
Jun 05 2010
dennis luehring <dl.soluz gmx.net> wrote:D still won't accept an delegat in an extern C because this type does not exists in the C worldNor do classes, and those certainly can be passed to a C-linkage function. Also, pointers to delegates can be passed to C-linkage functions. A delegate is nothing but a struct, and as such there is no reason for it not to be passable to a C-linkage function. I say this is a bug. -- Simen
Jun 06 2010
Am 06.06.2010 11:33, schrieb Simen kjaeraas:Also, pointers to delegates can be passed to C-linkage functions. A delegate is nothing but a struct, and as such there is no reason for it not to be passable to a C-linkage function.my fault - yes its possible to use delegates in non D but delegat-struct knowing languages (and a small pice of special calling code), sorry Zarathrustra i missed the point of your post in wholeI say this is a bug.me too are delegats part of the ABI, i can't find a delegat calling scheme in the ABI-Description - should this be in EAX, as last/first part on stack, ECX? wouldn't it be nice to have an complete call/use D features through c example around?
Jun 06 2010
my fault - yes its possible to use delegates in non D but delegat-struct knowing languages (and a small pice of special calling code), sorry Zarathrustra i missed the point of your post in wholeNo problem, I'm glad that we have reached an agreement.wouldn't it be nice to have an complete call/use D features through c example around?It would be great, if the DMC will provide such extensions like the dthiscall (for member functions) and the dcall (for static functions). Additionally would be great if DMC will works on other OS than MSWindows. But probably there are only my dreams ;) Btw. I think there is a good chance for create the set examples which show how to use D features on the C level. I will thinking about it in my free time :) The idea is really interesting and it would be useful(especially to better understand these mechanisms) for some people.are delegats part of the ABI, i can't find a delegat calling scheme in the ABI-Description - should this be in EAX, as last/first part on stack, ECX?The delegates are called by exactly same way as any other member function. Put ptr = 'this'(context pointer) to EAX and call funcptr (pointer to function). If I remember well, the 'this' pointer is passed to functions by ECX in C++. The delegate structure layout is described in ABI. ABI, disassembler and trail-end-error method will give you (and me too, because I still need to explore many things) an answer to many questions.I say this is a bug.Thanks for confirming my suspicions.
Jun 06 2010
Zarathustra:I think there is a good chance for create the set examples which show how to use D features on the C level. I will thinking about it in my free time :) The idea is really interesting and it would be useful(especially to better understand these mechanisms) for some people.I have asked for something similar. In such explanations I'd even like some boxes&arrows diagrams that show the data structures with the pointers, etc. Even few of such images can improve the understanding. Bye, bearophile
Jun 06 2010
Am 06.06.2010 17:30, schrieb Zarathustra:ok and it would be nice to have an clear description of this ABI+disasm trial-error-reusults in the ABI-Description - i think your example is needed to show walter the missing parts of the ABI-Docare delegats part of the ABI, i can't find a delegat calling scheme in the ABI-Description - should this be in EAX, as last/first part on stack, ECX?The delegates are called by exactly same way as any other member function. Put ptr = 'this'(context pointer) to EAX and call funcptr (pointer to function). If I remember well, the 'this' pointer is passed to functions by ECX in C++. The delegate structure layout is described in ABI. ABI, disassembler and trail-end-error method will give you (and me too, because I still need to explore many things) an answer to many questions.
Jun 06 2010
Simen kjaeraas wrote:dennis luehring <dl.soluz gmx.net> wrote:Yes, but I think that's a bug too. Quite a horrible one, in fact, since the class may get GC'd. On the "interfaceToC" page, class, type[], type[type] and delegate() are listed as having no C equivalent. They should all fail to compile.D still won't accept an delegat in an extern C because this type does not exists in the C worldNor do classes, and those certainly can be passed to a C-linkage function.
Jun 07 2010