digitalmars.D.learn - Call a function with a function pointer
- Namespace (13/13) Oct 10 2013 I have this function:
- Benjamin Thaut (8/21) Oct 10 2013 If you can change the signature of foo just add a extern(c) to the
- Namespace (9/32) Oct 10 2013 You mean like this?
- bearophile (8/15) Oct 10 2013 In theory that's correct, in practice the compiler refuses that,
- Namespace (6/22) Oct 10 2013 /d917/f732.d(8): Error: basic type expected, not extern
- bearophile (8/13) Oct 10 2013 It seems that even the new alias syntax doesn't support the
- Andrej Mitrovic (2/3) Oct 10 2013 I'm pretty sure I saw it filed somewhere. Can't find it though..
- bearophile (5/6) Oct 10 2013 I have just added the new test case :-)
- Benjamin Thaut (28/52) Oct 13 2013 I found a possible workaround. Its ugly as hell, but at least it works
- Artur Skawina (5/33) Oct 13 2013 There's no need for such ugly workarounds -- this is just a problem with
- Benjamin Thaut (2/35) Oct 13 2013 Oh so this bug was fixed? Thats good to know.
- Dicebot (5/21) Oct 10 2013 That is limitation of current extern - it can only be attached to
- Dicebot (3/16) Oct 10 2013 Wrap it in a lambda. Or change foo() signature to accept
- Namespace (2/20) Oct 10 2013 Example? I do not use lambdas often.
- Namespace (21/21) Oct 10 2013 ----
- Dicebot (11/32) Oct 10 2013 You are using short lambda syntax "a => b". Here `b` is always
- Artur Skawina (18/41) Oct 11 2013 It's probably not just "incompetence" (the compiler is able to figure th...
- Dicebot (4/28) Oct 11 2013 Agreed.
I have this function: ---- void foo(T)(void function(T*) test) { } ---- And want to call it with a C function: ---- foo!(SDL_Surface)(SDL_FreeSurface); ---- but I get: Fehler 1 Error: foo (void function(SDL_Surface*) test) is not callable using argument types (extern (C) void function(SDL_Surface*) nothrow) What would be the smartest solution?
Oct 10 2013
Am 10.10.2013 16:13, schrieb Namespace:I have this function: ---- void foo(T)(void function(T*) test) { } ---- And want to call it with a C function: ---- foo!(SDL_Surface)(SDL_FreeSurface); ---- but I get: Fehler 1 Error: foo (void function(SDL_Surface*) test) is not callable using argument types (extern (C) void function(SDL_Surface*) nothrow) What would be the smartest solution?If you can change the signature of foo just add a extern(c) to the function pointer declaration. Otherwise just wrap the SDL_FreeSurface call into a delegate on the caller side. -- Kind Regards Benjamin Thaut
Oct 10 2013
On Thursday, 10 October 2013 at 14:26:37 UTC, Benjamin Thaut wrote:Am 10.10.2013 16:13, schrieb Namespace:You mean like this? ---- void foo(T)(extern(C) void function(T*) func) { } ---- That prints: Error: basic type expected, not externI have this function: ---- void foo(T)(void function(T*) test) { } ---- And want to call it with a C function: ---- foo!(SDL_Surface)(SDL_FreeSurface); ---- but I get: Fehler 1 Error: foo (void function(SDL_Surface*) test) is not callable using argument types (extern (C) void function(SDL_Surface*) nothrow) What would be the smartest solution?If you can change the signature of foo just add a extern(c) to the function pointer declaration. Otherwise just wrap the SDL_FreeSurface call into a delegate on the caller side.
Oct 10 2013
Namespace:You mean like this? ---- void foo(T)(extern(C) void function(T*) func) { } ---- That prints: Error: basic type expected, not externIn theory that's correct, in practice the compiler refuses that, it's in Bugzilla, so try to define the type outside the signature (untested): alias TF = extern(C) void function(T*); void foo(T)(TF func) {} Bye, bearophile
Oct 10 2013
On Thursday, 10 October 2013 at 15:15:45 UTC, bearophile wrote:Namespace:/d917/f732.d(8): Error: basic type expected, not extern /d917/f732.d(8): Error: semicolon expected to close alias declaration /d917/f732.d(8): Error: no identifier for declarator void function(T*)You mean like this? ---- void foo(T)(extern(C) void function(T*) func) { } ---- That prints: Error: basic type expected, not externIn theory that's correct, in practice the compiler refuses that, it's in Bugzilla, so try to define the type outside the signature (untested): alias TF = extern(C) void function(T*); void foo(T)(TF func) {} Bye, bearophile
Oct 10 2013
Namespace:/d917/f732.d(8): Error: basic type expected, not extern /d917/f732.d(8): Error: semicolon expected to close alias declaration /d917/f732.d(8): Error: no identifier for declarator void function(T*)It seems that even the new alias syntax doesn't support the extern :-) Perhaps this bug is not yet in Bugzilla. Try: alias extern(C) void function(T*) TF; void foo(T)(TF func) {} Bye, bearophile
Oct 10 2013
On 10/10/13, bearophile <bearophileHUGS lycos.com> wrote:Perhaps this bug is not yet in Bugzilla.I'm pretty sure I saw it filed somewhere. Can't find it though..
Oct 10 2013
Andrej Mitrovic:I'm pretty sure I saw it filed somewhere. Can't find it though..I have just added the new test case :-) http://d.puremagic.com/issues/show_bug.cgi?id=6754 Bye, bearophile
Oct 10 2013
Am 10.10.2013 17:45, schrieb Namespace:On Thursday, 10 October 2013 at 15:15:45 UTC, bearophile wrote:I found a possible workaround. Its ugly as hell, but at least it works until the bugs are fixed. The trick is to make a helper struct. Define the function you want within that, and then use typeof to get the type. import std.stdio; extern(C) void testFunc(int* ptr) { *ptr = 5; } struct TypeHelper(T) { extern(C) static void func(T*); alias typeof(&func) func_t; } void Foo(T)(TypeHelper!T.func_t func, T* val) { func(val); } void main(string[] args) { pragma(msg, TypeHelper!int.func_t.stringof); int test = 0; Foo!int(&testFunc, &test); writefln("%d", test); } -- Kind Regards Benjamin ThautNamespace:/d917/f732.d(8): Error: basic type expected, not extern /d917/f732.d(8): Error: semicolon expected to close alias declaration /d917/f732.d(8): Error: no identifier for declarator void function(T*)You mean like this? ---- void foo(T)(extern(C) void function(T*) func) { } ---- That prints: Error: basic type expected, not externIn theory that's correct, in practice the compiler refuses that, it's in Bugzilla, so try to define the type outside the signature (untested): alias TF = extern(C) void function(T*); void foo(T)(TF func) {} Bye, bearophile
Oct 13 2013
On 10/13/13 16:43, Benjamin Thaut wrote:Am 10.10.2013 17:45, schrieb Namespace:There's no need for such ugly workarounds -- this is just a problem with the *new* alias syntax. The old one accepts it (unless this changed recently): alias extern(C) static void function(int*) Func_t; arturOn Thursday, 10 October 2013 at 15:15:45 UTC, bearophile wrote:I found a possible workaround. Its ugly as hell, but at least it works until the bugs are fixed.Namespace:/d917/f732.d(8): Error: basic type expected, not extern /d917/f732.d(8): Error: semicolon expected to close alias declaration /d917/f732.d(8): Error: no identifier for declarator void function(T*)You mean like this? ---- void foo(T)(extern(C) void function(T*) func) { } ---- That prints: Error: basic type expected, not externIn theory that's correct, in practice the compiler refuses that, it's in Bugzilla, so try to define the type outside the signature (untested): alias TF = extern(C) void function(T*); void foo(T)(TF func) {} Bye, bearophile
Oct 13 2013
Am 13.10.2013 17:17, schrieb Artur Skawina:On 10/13/13 16:43, Benjamin Thaut wrote:Oh so this bug was fixed? Thats good to know.Am 10.10.2013 17:45, schrieb Namespace:There's no need for such ugly workarounds -- this is just a problem with the *new* alias syntax. The old one accepts it (unless this changed recently): alias extern(C) static void function(int*) Func_t; arturOn Thursday, 10 October 2013 at 15:15:45 UTC, bearophile wrote:I found a possible workaround. Its ugly as hell, but at least it works until the bugs are fixed.Namespace:/d917/f732.d(8): Error: basic type expected, not extern /d917/f732.d(8): Error: semicolon expected to close alias declaration /d917/f732.d(8): Error: no identifier for declarator void function(T*)You mean like this? ---- void foo(T)(extern(C) void function(T*) func) { } ---- That prints: Error: basic type expected, not externIn theory that's correct, in practice the compiler refuses that, it's in Bugzilla, so try to define the type outside the signature (untested): alias TF = extern(C) void function(T*); void foo(T)(TF func) {} Bye, bearophile
Oct 13 2013
On Thursday, 10 October 2013 at 15:15:45 UTC, bearophile wrote:Namespace:That is limitation of current extern - it can only be attached to symbol declarations, not types. AFAIK you need to do `extern(C) alias TF = ...` but anyway this method is very likely to break IFTI completely.You mean like this? ---- void foo(T)(extern(C) void function(T*) func) { } ---- That prints: Error: basic type expected, not externIn theory that's correct, in practice the compiler refuses that, it's in Bugzilla, so try to define the type outside the signature (untested): alias TF = extern(C) void function(T*); void foo(T)(TF func) {} Bye, bearophile
Oct 10 2013
On Thursday, 10 October 2013 at 14:13:47 UTC, Namespace wrote:I have this function: ---- void foo(T)(void function(T*) test) { } ---- And want to call it with a C function: ---- foo!(SDL_Surface)(SDL_FreeSurface); ---- but I get: Fehler 1 Error: foo (void function(SDL_Surface*) test) is not callable using argument types (extern (C) void function(SDL_Surface*) nothrow) What would be the smartest solution?Wrap it in a lambda. Or change foo() signature to accept `extern(C)` functions - you can't just mix calling convention.
Oct 10 2013
On Thursday, 10 October 2013 at 14:28:20 UTC, Dicebot wrote:On Thursday, 10 October 2013 at 14:13:47 UTC, Namespace wrote:Example? I do not use lambdas often.I have this function: ---- void foo(T)(void function(T*) test) { } ---- And want to call it with a C function: ---- foo!(SDL_Surface)(SDL_FreeSurface); ---- but I get: Fehler 1 Error: foo (void function(SDL_Surface*) test) is not callable using argument types (extern (C) void function(SDL_Surface*) nothrow) What would be the smartest solution?Wrap it in a lambda.
Oct 10 2013
On Thursday, 10 October 2013 at 14:40:09 UTC, Namespace wrote:Example? I do not use lambdas often.void foo(T)(void function(T*) test) { } extern(C) void bar(int*) { } void main() { foo( (int* a) => bar(a) ); } I don't know to what extent IFTI can work here though.
Oct 10 2013
On Thursday, 10 October 2013 at 14:44:00 UTC, Dicebot wrote:On Thursday, 10 October 2013 at 14:40:09 UTC, Namespace wrote:That works. Thanks.Example? I do not use lambdas often.void foo(T)(void function(T*) test) { } extern(C) void bar(int*) { } void main() { foo( (int* a) => bar(a) ); } I don't know to what extent IFTI can work here though.
Oct 10 2013
---- import std.stdio; void foo1(void function(void*) fp) { } void foo2(void function(int) fp) { } void foo3(void*) { } void main() { foo1((void* ptr) => ( assert(ptr is null) )); foo2((int a) => ( a + 1 )); /// Fails: Error: function foo2 (void function(int) fp) is not callable using argument types (int function(int a) pure nothrow safe) foo1(&foo3); void foo4(void function(void*) fp) { } foo1(&foo4); /// Fails: Error: function foo1 (void function(void*) fp) is not callable using argument types (void delegate(void function(void*) fp)) } ---- Can someone explain that to me?
Oct 10 2013
On Thursday, 10 October 2013 at 17:47:54 UTC, Namespace wrote:---- import std.stdio; void foo1(void function(void*) fp) { } void foo2(void function(int) fp) { } void foo3(void*) { } void main() { foo1((void* ptr) => ( assert(ptr is null) )); foo2((int a) => ( a + 1 )); /// Fails: Error: function foo2 (void function(int) fp) is not callable using argument types (int function(int a) pure nothrow safe) foo1(&foo3); void foo4(void function(void*) fp) { } foo1(&foo4); /// Fails: Error: function foo1 (void function(void*) fp) is not callable using argument types (void delegate(void function(void*) fp)) } ---- Can someone explain that to me?You are using short lambda syntax "a => b". Here `b` is always return statement. It is equivalent to "(a) { return b; }". And your `foo2` signature expects lambda returning void, like "(a) { return; }" Second error is DMD incompetence in deducing minimal required type of nested function. It always treats them as delegates (== having hidden context pointer) even if those do not refer any actual context. And plain lambdas are of course binary incompatible with delegates (closures) because of that extra pointer field.
Oct 10 2013
On 10/10/13 20:54, Dicebot wrote:On Thursday, 10 October 2013 at 17:47:54 UTC, Namespace wrote:It's probably not just "incompetence" (the compiler is able to figure this out in other contexts), but a deliberate choice. Having function types depend on their bodies would not be a good idea. Eg int c; auto f() { int a = 42; int f1() { return a; } int f2() { return 0; } return !c?&f1:&f2; } Mark f2 as 'static' and this code will no longer compile. If that would be done automatically then you'd have to 'undo' it manually, which would cause even more problems (consider generic code, which isn't prepared to handle this). artur [1] at least without other language improvements; enabling overloading on 'static', plus a few other enhancements, would change the picture.---- import std.stdio; void foo1(void function(void*) fp) { } void foo2(void function(int) fp) { } void foo3(void*) { } void main() { foo1((void* ptr) => ( assert(ptr is null) )); foo2((int a) => ( a + 1 )); /// Fails: Error: function foo2 (void function(int) fp) is not callable using argument types (int function(int a) pure nothrow safe) foo1(&foo3); void foo4(void function(void*) fp) { } foo1(&foo4); /// Fails: Error: function foo1 (void function(void*) fp) is not callable using argument types (void delegate(void function(void*) fp)) } ----You are using short lambda syntax "a => b". Here `b` is always return statement. It is equivalent to "(a) { return b; }". And your `foo2` signature expects lambda returning void, like "(a) { return; }" Second error is DMD incompetence in deducing minimal required type of nested function. It always treats them as delegates (== having hidden context pointer) even if those do not refer any actual context. And plain lambdas are of course binary incompatible with delegates (closures) because of that extra pointer field.
Oct 11 2013
On Friday, 11 October 2013 at 15:55:17 UTC, Artur Skawina wrote:It's probably not just "incompetence" (the compiler is able to figure this out in other contexts), but a deliberate choice. Having function types depend on their bodies would not be a good idea. Eg int c; auto f() { int a = 42; int f1() { return a; } int f2() { return 0; } return !c?&f1:&f2; } Mark f2 as 'static' and this code will no longer compile. If that would be done automatically then you'd have to 'undo' it manually, which would cause even more problems (consider generic code, which isn't prepared to handle this). artur [1] at least without other language improvements; enabling overloading on 'static', plus a few other enhancements, would change the picture.Agreed. However, I do feel uncomfortable with new habit to put `static` everywhere to avoid hidden compiler "help" :(
Oct 11 2013