Thread overview | |||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
June 04, 2010 delegates with C linkage | ||||
---|---|---|---|---|
| ||||
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. |
June 05, 2010 Re: delegates with C linkage | ||||
---|---|---|---|---|
| ||||
Posted in reply to Zarathustra | 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.
|
June 05, 2010 Re: delegates with C linkage | ||||
---|---|---|---|---|
| ||||
Posted in reply to Mike Parker | 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 |
June 05, 2010 Re: delegates with C linkage | ||||
---|---|---|---|---|
| ||||
Posted in reply to Mike Parker | > 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. |
June 05, 2010 Re: delegates with C linkage | ||||
---|---|---|---|---|
| ||||
Posted in reply to Zarathustra | Am 05.06.2010 13:33, schrieb Zarathustra:
>> 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.
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 object
|
June 05, 2010 Re: delegates with C linkage | ||||
---|---|---|---|---|
| ||||
Posted in reply to dennis luehring | > 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 object gcc: __attribute__((regparm (1))) put_first_paramerter_to_eax(d_object this){...} __attribute__((regparm (1))) - puts the first function parameter to EAX. |
June 05, 2010 Re: delegates with C linkage | ||||
---|---|---|---|---|
| ||||
Posted in reply to Zarathustra | Am 05.06.2010 15:42, 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 object
>
> gcc:
> __attribute__((regparm (1))) put_first_paramerter_to_eax(d_object this){...}
>
> __attribute__((regparm (1))) - puts the first function parameter to EAX.
ok so your using gcc and some "extensions"
|
June 05, 2010 Re: delegates with C linkage | ||||
---|---|---|---|---|
| ||||
Posted in reply to dennis luehring | Am 05.06.2010 16:03, schrieb dennis luehring:
> Am 05.06.2010 15:42, 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 object
>>
>> gcc:
>> __attribute__((regparm (1))) put_first_paramerter_to_eax(d_object this){...}
>>
>> __attribute__((regparm (1))) - puts the first function parameter to EAX.
>
> ok so your using gcc and some "extensions"
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?
|
June 05, 2010 Re: delegates with C linkage | ||||
---|---|---|---|---|
| ||||
Posted in reply to dennis luehring | > 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 Maybe 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 |
June 06, 2010 Re: delegates with C linkage | ||||
---|---|---|---|---|
| ||||
Posted in reply to dennis luehring | 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 world Nor 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 |
Copyright © 1999-2021 by the D Language Foundation