Re: Function Pointer
On Wednesday, 30 August 2023 at 21:12:57 UTC, Paul Backus wrote: On Wednesday, 30 August 2023 at 17:48:19 UTC, Vino wrote: Hi All, Request your help on hot to create a pointer for a function whose function type is Result. ``` ReturnType!(typeof()).stringof; // Result From Vino ``` To get a function pointer type from a function type, you can add `*` on the end: void func(int) {} alias FuncType = typeof(func); pragma(msg, FuncType); // void(int) alias FuncPtrType = FuncType*; pragma(msg, FuncPtrType); // void function(int) static assert(is(FuncPtrType == typeof())); Thank you very much
Re: Function Pointer
On Wednesday, 30 August 2023 at 17:48:19 UTC, Vino wrote: Hi All, Request your help on hot to create a pointer for a function whose function type is Result. ``` ReturnType!(typeof()).stringof; // Result From Vino ``` To get a function pointer type from a function type, you can add `*` on the end: void func(int) {} alias FuncType = typeof(func); pragma(msg, FuncType); // void(int) alias FuncPtrType = FuncType*; pragma(msg, FuncPtrType); // void function(int) static assert(is(FuncPtrType == typeof()));
Re: How can a function pointer required to be extern(C)?
On Wednesday, 12 April 2023 at 21:00:04 UTC, John Chapman wrote: You can also express it like this: ```d extern(C) alias FuncPtr = void* function(void*); ``` Thank you! This is how I was planning to do anyway because other that the fact that I like the syntax of that a little bit more, this code will be part of the library so there will not be any function to take its type so I cannot do this the other away even if I wanted. Have an amazing day my friend!
Re: How can a function pointer required to be extern(C)?
On Wednesday, 12 April 2023 at 20:36:59 UTC, H. S. Teoh wrote: IMO this is a bug either in D's syntax or in the parser. I'd file an enhancement request. In the meantime, you can use alias as a workaround: ---snip--- extern(C) void* abc(void*) {return null;} alias FuncPtr = typeof(); pragma(msg, typeof(abc)); pragma(msg, typeof()); //void wrapper(extern(C) void* function(void*) callback) {} // NG void wrapper(FuncPtr callback) {} // OK pragma(msg, typeof(wrapper)); ---snip--- T Thank you! As long as there is a way to do it with aliases, I don't think that there is a reason to even bother the developers. I mean, it will just save me 1 line of code in my whole project (because I don't think I'll use this even again somewhere else) so I don't think it's worth it. Thank you for your help. Best thing with Dlang is the community ;) I wish you to have an amazing day!
Re: How can a function pointer required to be extern(C)?
On Wednesday, 12 April 2023 at 20:36:59 UTC, H. S. Teoh wrote: ---snip--- extern(C) void* abc(void*) {return null;} alias FuncPtr = typeof(); You can also express it like this: ```d extern(C) alias FuncPtr = void* function(void*); ```
Re: How can a function pointer required to be extern(C)?
On Wed, Apr 12, 2023 at 08:23:51PM +, rempas via Digitalmars-d-learn wrote: > Sorry if the title doesn't make any sense, let me explain. So, I do have the > following code that does not compile: > > ```d > import core.sys.posix.pthread; /* The library */ > > struct Thread { > private: > pthread_t thread_id; > > public: > this(void* function(void*) func, void* arg = null, scope > const(pthread_attr_t*) attr = null) { > pthread_create(_id, attr, func, arg); > } > > @property: > pthread_t id() { return this.thread_id; } > } > > ``` > > Yes, I'm trying to "encapsulate" the Pthread (POSIX threads) API. > Normally, the function pointer that is passed to "pthread_create" must > be "extern(C)" and this is the complaining that the compile does. So, > I'm thinking to replace the constructor to this: > > ```d > this(extern(C) void* function(void*) func, void* arg = null, > scope const(pthread_attr_t*) attr = null) > { pthread_create(_id, attr, func, arg); } > ``` > > I just added "extern(C)" before the type. This is how it looks in the > error message so it must work right? Well... it doesn't. And here I am > wondering why. Any ideas? IMO this is a bug either in D's syntax or in the parser. I'd file an enhancement request. In the meantime, you can use alias as a workaround: ---snip--- extern(C) void* abc(void*) {return null;} alias FuncPtr = typeof(); pragma(msg, typeof(abc)); pragma(msg, typeof()); //void wrapper(extern(C) void* function(void*) callback) {} // NG void wrapper(FuncPtr callback) {} // OK pragma(msg, typeof(wrapper)); ---snip--- T -- A programming language should be a toolbox for the programmer to draw upon, not a minefield of dangerous explosives that you have to very carefully avoid touching in the wrong way.
How can a function pointer required to be extern(C)?
Sorry if the title doesn't make any sense, let me explain. So, I do have the following code that does not compile: ```d import core.sys.posix.pthread; /* The library */ struct Thread { private: pthread_t thread_id; public: this(void* function(void*) func, void* arg = null, scope const(pthread_attr_t*) attr = null) { pthread_create(_id, attr, func, arg); } @property: pthread_t id() { return this.thread_id; } } ``` Yes, I'm trying to "encapsulate" the Pthread (POSIX threads) API. Normally, the function pointer that is passed to "pthread_create" must be "extern(C)" and this is the complaining that the compile does. So, I'm thinking to replace the constructor to this: ```d this(extern(C) void* function(void*) func, void* arg = null, scope const(pthread_attr_t*) attr = null) { pthread_create(_id, attr, func, arg); } ``` I just added "extern(C)" before the type. This is how it looks in the error message so it must work right? Well... it doesn't. And here I am wondering why. Any ideas?
Re: Can't assign extern(C) function pointer to D variable?
On Tuesday, 22 November 2022 at 21:32:43 UTC, Hipreme wrote: You need to create an alias containing your callback type. Thanks both!! I have all the pieces of the puzzle. I'm actually staying with the wrapping template solution. (Because the strongly typed one turns out too convoluted, and because it allows the remaining ScopeCleanup struct to be more general purpose, for non-C functions, and for functions that don't return void but an error code which I want to discard.) The first problem was indeed that a C function pointer "is not" a D one. So annotating the variable with extern(C) can indeed solve it. I had actually tried this, but it was not compiling for another reason. The next reason (as you see in the GitHub link) is that the variable in question is a (constructor) parameter. D can't seem to compile extern(C) inlined somewhere else. Indeed aliasing takes care of this second problem: alias CFunction = extern(C) void function(); /// RAII object that does nothing but calling, when destructed, the function passed at construction. struct ScopeCleanup { @disable this(); this(CFunction cleanup) { this.cleanup = cleanup; } ~this() { cleanup(); } CFunction cleanup; } Now this module compiles. BUT the code trying to call this constructor doesn't compile, when called with C function such as SDL_Quit imported from the SDL lib, or IMG_Quit imported from the SDL_image lib. From the compiler error I learn that the imported function is not only extern(C) but also nothrow @nogc. Fair enough, I add it to the alias. BUT still no good, because (as I learn from the same compiler error) this binding imports these functions as extern(C) void function() nothrow @nogc* with this final "*" this turns out, from the D point of view, a "pointer to a function pointer" XD so it has to be called/de-referenced in this way (in destructor): alias CFunctionPtr = extern(C) void function() nothrow @nogc*; /// RAII object that does nothing but calling, when destructed, the function passed at construction. struct ScopeCleanup { @disable this(); this(CFunctionPtr cleanup) { this.cleanup = cleanup; } ~this() { (*cleanup)(); } CFunctionPtr cleanup; } Thanks guys for the learning, I'm staying with the template solution (thanks D), but let me know if you have more insights.
Re: Can't assign extern(C) function pointer to D variable?
On 22.11.22 22:11, XavierAP wrote: I was surprised when it didn't compile, though I immediately found it understandable... Already read through https://dlang.org/spec/interfaceToC.html and https://wiki.dlang.org/Bind_D_to_C Is it really the case (that an extern(C) function pointer cannot be assigned to a D variable)? Or is it a matter of annotating with the right attributes? If so, how? Works for me: import core.stdc.stdio: puts; auto p1 = extern (C) int function(const char* s) p2 = If you're trying to assign an `extern (C)` function pointer to an `extern (D)` one (the default), that cannot work. The compiler would emit code using D's calling convention, but the called function would assume C's calling convention.
Re: Can't assign extern(C) function pointer to D variable?
On Tuesday, 22 November 2022 at 21:11:37 UTC, XavierAP wrote: I was surprised when it didn't compile, though I immediately found it understandable... Already read through https://dlang.org/spec/interfaceToC.html and https://wiki.dlang.org/Bind_D_to_C [...] You need to create an alias containing your callback type. ```d alias DCallback = extern(C) void function(); DCallback cb; cb = yourCFunction; ```
Can't assign extern(C) function pointer to D variable?
I was surprised when it didn't compile, though I immediately found it understandable... Already read through https://dlang.org/spec/interfaceToC.html and https://wiki.dlang.org/Bind_D_to_C Is it really the case (that an extern(C) function pointer cannot be assigned to a D variable)? Or is it a matter of annotating with the right attributes? If so, how? Otherwise I'm interested in the best or most concise workaround. Is there a better one? I came up with a template solution: https://github.com/XavierAP/game-king/blob/master/source/scope_cleanup.d The problem I had was that this ScopeCleanup struct could not be constructed passing a pointer to a function imported from C (from the SDL library; you can browse around the same repo to see its usage; it's just a toy project that's barely started).
Re: function(pointer) as template argument, explicit template instantiation
On Friday, 31 December 2021 at 12:36:46 UTC, H. S. Teoh wrote: ``` void lyr(alias Fn)(ref R r) { Fn(r); } ``` Thanks! That helped me reinvent the engine.
Re: function(pointer) as template argument, explicit template instantiation
On Fri, Dec 31, 2021 at 11:52:21AM +, kdevel via Digitalmars-d-learn wrote: [...] > That is what I want to do. The function template lyr shall be > (explicitly) instantiated in order to put the resulting function > pointer into an AA. The call signature of lyr!(foo) and foo must be > the same. > > In C++ this looks like this: [...] struct R {} void lyr(alias Fn)(ref R r) { Fn(r); } void foo(ref R r) { } static immutable void function(ref R)[string] reg; shared static this() { // workaround for lack of CT AA initialization reg = [ "foo": , "lfoo": !foo, ]; } T -- Why waste time reinventing the wheel, when you could be reinventing the engine? -- Damian Conway
Re: function(pointer) as template argument, explicit template instantiation
On Friday, 31 December 2021 at 09:01:10 UTC, data pulverizer wrote: On Friday, 31 December 2021 at 00:57:26 UTC, kdevel wrote: Pointers are runtime entities and are not suitable template parameters (compile time). The address of a function does not change at runtime. The question is: Can functions (pointers) be used as template arguments? So assuming that you are trying to either pass a function constant of a specific type signature as a template argument, That is what I want to do. The function template lyr shall be (explicitly) instantiated in order to put the resulting function pointer into an AA. The call signature of lyr!(foo) and foo must be the same. In C++ this looks like this: ```C++ struct R { }; // typedef void (* Fn) (R &); // ptr version typedef void (& Fn) (R &); template static void lyr (R ) { // invoke f } static void foo (R ) { } /* ptr version static const std::map reg = { {"foo", }, {"lfoo", } // <--- func tmpl instantiation }; */ static const std::map reg = { {"foo", foo}, {"lfoo", lyr} // <--- func tmpl instantiation }; ```
Re: function(pointer) as template argument, explicit template instantiation
On Friday, 31 December 2021 at 03:02:08 UTC, Tejas wrote: [...] Is it okay to use template parameter instead of **template value** parameter? ```d class R { } void foo (R r) { } void lyr (fp_type, R) (fp_type fp, R r) { } pragma (msg, typeof ()); R r; void main(){ auto foo_ptr = lyr(foo_ptr, r); } ``` No, the type should be the same. I want to register lyr!() like this: ``` fn [string] reg = [ "foo": , "lfoo": !() ]; ```
Re: function(pointer) as template argument, explicit template instantiation
On Friday, 31 December 2021 at 00:57:26 UTC, kdevel wrote: ```dptr.d class R { } void foo (R r) { } alias fn = void function (R); void lyr (fn F) (R r) { } immutable fn foo_ptr = // line 14 pragma (msg, typeof (foo_ptr)); auto ptr = lyr!(foo_ptr);// line 17 ``` dmd reports: ``` immutable(void function(R)) dptr.d(14): Error: expression `& foo` is not a valid template value argument ``` If I comment out line 17 the code compiles. I want to put the explicitly instantiated function template into an immutable AA. How can that be phrased such that dmd compiles it? Pointers are runtime entities and are not suitable template parameters (compile time). So assuming that you are trying to either pass a function constant of a specific type signature as a template argument, or a function pointer as an argument with either a template specialisation or constraint: ``` class R {} void foo(R r){} alias fn = void function(R); //function compile time constant void lyr(fn fp_type)(R r){} //As template constraint void con(T)(T fun, R r) if(is(T == fn)) { fun(r); } /* //As template specialisation void con(T: fn)(T fun, R r) { fun(r); } */ //Function constant enum fn foo_ptr = (R r){}; pragma(msg, typeof(foo_ptr)); //Declared at compile time but only executable at runtime auto ptr = !(foo_ptr); void main() { //auto ptr = !(foo_ptr);//could declare this here ptr(new R()); fn new_ptr = con(new_ptr, new R()); } ```
Re: function(pointer) as template argument, explicit template instantiation
On Friday, 31 December 2021 at 00:57:26 UTC, kdevel wrote: ```dptr.d class R { } void foo (R r) { } alias fn = void function (R); void lyr (fn F) (R r) { } immutable fn foo_ptr = // line 14 pragma (msg, typeof (foo_ptr)); auto ptr = lyr!(foo_ptr);// line 17 ``` dmd reports: ``` immutable(void function(R)) dptr.d(14): Error: expression `& foo` is not a valid template value argument ``` If I comment out line 17 the code compiles. I want to put the explicitly instantiated function template into an immutable AA. How can that be phrased such that dmd compiles it? Is it okay to use template parameter instead of **template value** parameter? ```d class R { } void foo (R r) { } void lyr (fp_type, R) (fp_type fp, R r) { } pragma (msg, typeof ()); R r; void main(){ auto foo_ptr = lyr(foo_ptr, r); } ```
function(pointer) as template argument, explicit template instantiation
```dptr.d class R { } void foo (R r) { } alias fn = void function (R); void lyr (fn F) (R r) { } immutable fn foo_ptr = // line 14 pragma (msg, typeof (foo_ptr)); auto ptr = lyr!(foo_ptr);// line 17 ``` dmd reports: ``` immutable(void function(R)) dptr.d(14): Error: expression `& foo` is not a valid template value argument ``` If I comment out line 17 the code compiles. I want to put the explicitly instantiated function template into an immutable AA. How can that be phrased such that dmd compiles it?
Re: How to do a function pointer to "malloc" and "free"?
On Sunday, 17 October 2021 at 23:07:15 UTC, Elmar wrote: Do you have a link for more information how to initialize the D runtime? Export a function that calls this: http://druntime.dpldocs.info/core.runtime.Runtime.initialize.html And also export a function that calls this: http://druntime.dpldocs.info/core.runtime.Runtime.terminate.html And tell the user to call those when they load/unload the library. (It is pretty common for C libraries to require explicit init/term calls so they should be used to it.) They refcount internally so it is ok to call multiple times, just make sure the init and term are always paired. (btw the druntime actually exports them as extern(C) rt_init/rt_term but I'd still recommend you do your own anyway. if you do have extra work to do you can just do it there, and it can use whatever your lib naming conventions are. and besides im not sure if the extern(C) things are specified stable (even though they have been for as long as i can remember), whereas doing your own thing that `import core.runtime; return Runtime.initalize;` is. )
Re: How to do a function pointer to "malloc" and "free"?
On Sunday, 10 October 2021 at 17:14:30 UTC, Adam Ruppe wrote: On Sunday, 10 October 2021 at 13:52:57 UTC, Elmar wrote: The language subset "BetterC" is required for calling D functions from C though. This is false. You can use any D features when calling it from C, you just need to provide an init and term function that is called from C that runtime initialize and terminate for the full experience. BetterC helper librarys like Tanya or Tango do exist. I don't know tanya, but Tango has absolutely nothing to do with betterC. It is a set of classes that use the full runtime. That's nice! Do you have a link for more information how to initialize the D runtime? I just wondered about that because I thought it actually shouldn't be much more difficult than just linking the runtime into the foreign-language compiled program. I didn't find information on that. Maybe I didn't search long enough.
Re: How to do a function pointer to "malloc" and "free"?
On 10/10/21 6:44 AM, rempas wrote: I'm having the following C code: ``` static void* (*ppmalloc)(size_t) = malloc; static void (*ppfree)(void*) = free; ``` I want to covert this code in D so I try to do the following: ``` static void* function(size_t)*ppmalloc = malloc; static void function(void*)*ppfree = free; ``` If I do that, I'm getting the following error message: ``` Error: function `core.stdc.stdlib.malloc(ulong size)` is not callable using argument types `()` ``` I'm also trying to do the same using "pureMalloc" and "pureFree" instead but this time I'm getting the following error: ``` cannot implicitly convert expression `pureMalloc()(size_t size)` of type `void` to `extern (C) void* function(ulong)*` ``` Any ideas? I know most of this is answered already, but I would suggest actually just: ```d auto ppmalloc = ``` which all of D's type inference to allow you to declare the appropriate function type. BTW, you get the error because in D, empty parentheses are optional. So when you say `malloc`, it really means `malloc()`. Which is one big reason why the & operator is required. -Steve
Re: How to do a function pointer to "malloc" and "free"?
On Sunday, 10 October 2021 at 14:00:37 UTC, Elmar wrote: On Sunday, 10 October 2021 at 13:56:06 UTC, rempas wrote: Actually I know about BetterC and how to call C functions from D and visa versa. I would also disagree that "BetterC" is almost no improvement over C as about 90% of the language is there!! C++ classes are also supported Nice :-) , you're right. I need to be more optimistic here. Happy coding. Thanks a lot! Happy coding to you too!
Re: How to do a function pointer to "malloc" and "free"?
On Sunday, 10 October 2021 at 13:52:57 UTC, Elmar wrote: The language subset "BetterC" is required for calling D functions from C though. This is false. You can use any D features when calling it from C, you just need to provide an init and term function that is called from C that runtime initialize and terminate for the full experience. BetterC helper librarys like Tanya or Tango do exist. I don't know tanya, but Tango has absolutely nothing to do with betterC. It is a set of classes that use the full runtime.
Re: How to do a function pointer to "malloc" and "free"?
On Sunday, 10 October 2021 at 13:56:06 UTC, rempas wrote: Actually I know about BetterC and how to call C functions from D and visa versa. I would also disagree that "BetterC" is almost no improvement over C as about 90% of the language is there!! C++ classes are also supported Nice :-) , you're right. I need to be more optimistic here. Happy coding.
Re: How to do a function pointer to "malloc" and "free"?
On Sunday, 10 October 2021 at 13:52:57 UTC, Elmar wrote: The language subset "BetterC" is required for calling D functions from C though. Unfortunately, the runtime features of BetterC are limited and some of C's language features aren't availabe like C99 variable-length-arrays. "BetterC" is like programming in C with little more comfort but phobos is unusable which makes BetterC almost no improvement over C. BetterC helper librarys like Tanya or Tango do exist. Oh well, I could also be wrong with BetterC support of Tanya and Tango but both are alterantives to Phobos.
Re: How to do a function pointer to "malloc" and "free"?
On Sunday, 10 October 2021 at 13:52:57 UTC, Elmar wrote: Hopefully it will :-) . D has some good C support. You can call any C function from `D` by declaring it `extern(C) `. The language subset "BetterC" is required for calling D functions from C though. Unfortunately, the runtime features of BetterC are limited and some of C's language features aren't availabe like C99 variable-length-arrays. "BetterC" is like programming in C with little more comfort but phobos is unusable which makes BetterC almost no improvement over C. BetterC helper librarys like Tanya or Tango do exist. In that case it can indeed be better for you to convert the program's entry point into D code. This is unfortunate because it prevents C code bases from using D. There is a tool [C++ Conversion Wizard](https://rainers.github.io/visuald/visuald/CppConversion.html) which could be able to convert C++ and C to D but I don't know how good it is and whether it's usable for free on a GNU/Linux derivative OS. It's only half-automatic. Actually I know about BetterC and how to call C functions from D and visa versa. I would also disagree that "BetterC" is almost no improvement over C as about 90% of the language is there!! C++ classes are also supported
Re: How to do a function pointer to "malloc" and "free"?
On Sunday, 10 October 2021 at 13:10:27 UTC, rempas wrote: Thanks, I'm converting a library from C to D so I have to fix all the other bugs first to see If it's working but probably it will. Have an amazing day my friend! Hopefully it will :-) . D has some good C support. You can call any C function from `D` by declaring it `extern(C) `. The language subset "BetterC" is required for calling D functions from C though. Unfortunately, the runtime features of BetterC are limited and some of C's language features aren't availabe like C99 variable-length-arrays. "BetterC" is like programming in C with little more comfort but phobos is unusable which makes BetterC almost no improvement over C. BetterC helper librarys like Tanya or Tango do exist. In that case it can indeed be better for you to convert the program's entry point into D code. This is unfortunate because it prevents C code bases from using D. There is a tool [C++ Conversion Wizard](https://rainers.github.io/visuald/visuald/CppConversion.html) which could be able to convert C++ and C to D but I don't know how good it is and whether it's usable for free on a GNU/Linux derivative OS. It's only half-automatic.
Re: How to do a function pointer to "malloc" and "free"?
On Sunday, 10 October 2021 at 11:26:18 UTC, Elmar wrote: Hello rempas. This is the way: ```d import core.stdc.stdlib : malloc, free; extern(C) void* function(ulong) mallocPointer = extern(C) void function(void*) freePointer = ``` `function` in the type is already a function pointer. Not immediately obvious though: You also must annotate the type with `extern(C)` otherwise it will not work. Thanks, I'm converting a library from C to D so I have to fix all the other bugs first to see If it's working but probably it will. Have an amazing day my friend!
Re: How to do a function pointer to "malloc" and "free"?
On Sunday, 10 October 2021 at 10:44:15 UTC, rempas wrote: I'm having the following C code: ``` static void* (*ppmalloc)(size_t) = malloc; static void (*ppfree)(void*) = free; ``` I want to covert this code in D so I try to do the following: ``` static void* function(size_t)*ppmalloc = malloc; static void function(void*)*ppfree = free; ``` If I do that, I'm getting the following error message: ``` Error: function `core.stdc.stdlib.malloc(ulong size)` is not callable using argument types `()` ``` I'm also trying to do the same using "pureMalloc" and "pureFree" instead but this time I'm getting the following error: ``` cannot implicitly convert expression `pureMalloc()(size_t size)` of type `void` to `extern (C) void* function(ulong)*` ``` Any ideas? Hello rempas. This is the way: ```d import core.stdc.stdlib : malloc, free; extern(C) void* function(ulong) mallocPointer = extern(C) void function(void*) freePointer = ``` `function` in the type is already a function pointer. Not immediately obvious though: You also must annotate the type with `extern(C)` otherwise it will not work.
How to do a function pointer to "malloc" and "free"?
I'm having the following C code: ``` static void* (*ppmalloc)(size_t) = malloc; static void (*ppfree)(void*) = free; ``` I want to covert this code in D so I try to do the following: ``` static void* function(size_t)*ppmalloc = malloc; static void function(void*)*ppfree = free; ``` If I do that, I'm getting the following error message: ``` Error: function `core.stdc.stdlib.malloc(ulong size)` is not callable using argument types `()` ``` I'm also trying to do the same using "pureMalloc" and "pureFree" instead but this time I'm getting the following error: ``` cannot implicitly convert expression `pureMalloc()(size_t size)` of type `void` to `extern (C) void* function(ulong)*` ``` Any ideas?
Re: Function Pointer Not Working
I will wait with this code. WaitForSingleObject(threading, INFINITE);
Re: Function Pointer Not Working
On Thursday, 19 November 2020 at 15:51:09 UTC, Kagamin wrote: The delegate is stored on the stack of the calling thread, the created thread loads it from there, but the calling thread doesn't wait for that and clobbers the stack right away. If you were lucky your code would crash. The thread that I do wait ultil function is finished. Using a while with 3 seconds to verify if thread id is in running list, and break if not finishing owner thread.
Re: Function Pointer Not Working
The delegate is stored on the stack of the calling thread, the created thread loads it from there, but the calling thread doesn't wait for that and clobbers the stack right away. If you were lucky your code would crash.
Re: Function Pointer Not Working
Solved replacing this line: CreateThread(null, 0, &_fun, , 0, null); to this code: task!({CreateThread(null, 0, &_fun, , 0, null);}).executeInNewThread();
Re: Function Pointer Not Working
On Thursday, 19 November 2020 at 04:23:13 UTC, Marcone wrote: // Function threadingw() void threadingw(HWND hwn, void delegate() fun) nothrow { try { // Function _fun() extern(Windows) uint _fun(void * arg){ (*(cast(void delegate()*) arg))(); // Do not show "Hello World!" :( return 0; } CreateThread(null, 0, &_fun, , 0, null); } catch(Throwable){} } void main(){ null.threadingw({writeln("Hello World!");}); } A delegate is a "fat" pointer (function pointer + context), so it can't fit in a void*. You could do something like the following to "uncurry" the delegate and extract its context to a void* and a regular function, which can then combine the void* given to it later to call the original delegate: import std.traits; auto uncurryDelegate(alias anchor, alias target)() { alias Args = Parameters!target; alias R = ReturnType!target; alias ContextPtr = void*; alias Dg = typeof(); union Delegate { Dg dg; struct { void* ptr; void* funcptr; } } auto dg = Delegate(); __gshared void* funcptr; // Will always be the same for this instantiation funcptr = ().funcptr; static struct Result { R function(ContextPtr ptr, Args args) fun; ContextPtr context; } static R fun(ContextPtr ptr, Args args) { Delegate dg; dg.funcptr = funcptr; dg.ptr = ptr; return dg.dg(args); } return Result(, dg.ptr); } auto uncurryDelegate(alias target)() { return uncurryDelegate!(target, target); } unittest { int fun(int i) { return i + 1; } auto r = uncurryDelegate!fun; assert(r.fun(r.context, 2) == 3); } unittest { struct S { int i; int fun(int j) { return i + j; } auto funUncurried() { return uncurryDelegate!(i, fun); } } auto s = S(2); auto r = s.funUncurried(); assert(r.fun(r.context, 3) == 5); } Sadly you can't write `static immutable void* funcptr = ().funcptr;`, because the compiler tries to evaluate first. Alternatively you could do this (not recommended): https://stackoverflow.com/a/8656294/21501
Function Pointer Not Working
// Function threadingw() void threadingw(HWND hwn, void delegate() fun) nothrow { try { // Function _fun() extern(Windows) uint _fun(void * arg){ (*(cast(void delegate()*) arg))(); // Do not show "Hello World!" :( return 0; } CreateThread(null, 0, &_fun, , 0, null); } catch(Throwable){} } void main(){ null.threadingw({writeln("Hello World!");}); }
Re: is function pointer least significant bit always zero ?
On 10/27/2018 09:16 PM, learnfirst1 wrote: I plan to use function pointer least significant bit to store some information. If there is no GC on my system, I think it will help the memory is well aligned. The question is all the function least significant bit is zero ? Most definitely. Related presentation: http://dconf.org/2016/talks/sechet.html Ali
is function pointer least significant bit always zero ?
I plan to use function pointer least significant bit to store some information. If there is no GC on my system, I think it will help the memory is well aligned. The question is all the function least significant bit is zero ?
Re: Checking if a function pointer is set or null
On Monday, April 09, 2018 00:25:08 solidstate1991 via Digitalmars-d-learn wrote: > Would the if(!(myFunctionPointer is null)){} work is I > intended? You can also do if(myFunctionPointer !is null) - Jonathan M Davis
Re: Checking if a function pointer is set or null
On Monday, 9 April 2018 at 00:25:08 UTC, solidstate1991 wrote: Would the if(!(myFunctionPointer is null)){} work is I intended? Yes, that works as you expect https://run.dlang.io/is/ZTtm0P
Checking if a function pointer is set or null
Would the if(!(myFunctionPointer is null)){} work is I intended?
Re: Get a string of a function name from a function pointer?
On 07/10/2017 05:26 AM, SauceKode wrote: > I need to pass a group of (C) function pointers to another language from > D... is there a way to derrive a name from a function pointer? Or do I > have to manually list out the names? libunwind should be able to provide that functionality. Otherwise, no, the function pointer itself does not contain any additional information. Ali
Get a string of a function name from a function pointer?
I need to pass a group of (C) function pointers to another language from D... is there a way to derrive a name from a function pointer? Or do I have to manually list out the names?
Re: The reason for SIGSEGV function pointer problem
Thanks also to Paolo Invernizzi and ag0aep6g for answering with a similar response. Using Mike's response as it has extra detail. On Wed, 2017-06-07 at 20:00 +0200, Mike Wey via Digitalmars-d-learn wrote: > On 06/07/2017 06:50 PM, Russel Winder via Digitalmars-d-learn wrote: > > So why isn't a thing of type check_frontend_t* > > AFAIK, you would usually translate: > > > typedef int (check_frontend_t*)(void *args, struct dvb_v5_fe_parms > *parms); The C code in dvb-scan.h is actually: typedef int (check_frontend_t)(void *args, struct dvb_v5_fe_parms *parms); > into: > > alias check_frontend_t = extern(C) int function (void* args, > dvb_v5_fe_parms* parms); I can't remember what DStep produced initially, but the above is what I have in dvb_scan.d. Per se it seems consistent, but then functions in D, and their signatures, may be totally different to functions in C. > The problem there is that libdvdv5 defines it as (check_frontend_t) > and > not (check_frontend_t*). > To get around that you can ommit the * in the declaration of > dvb_scan_transponder, and then you should be able to pass > > to it. I am now at the stage of wondering if I remember C semantics, C++ semantics, and D semantics for "pointers to functions". There may also be an issue of there being a bug in DStep… -- Russel. = Dr Russel Winder t: +44 20 7585 2200 voip: sip:russel.win...@ekiga.net 41 Buckmaster Roadm: +44 7770 465 077 xmpp: rus...@winder.org.uk London SW11 1EN, UK w: www.russel.org.uk skype: russel_winder signature.asc Description: This is a digitally signed message part
Re: The reason for SIGSEGV function pointer problem
On 06/07/2017 06:50 PM, Russel Winder via Digitalmars-d-learn wrote: So why isn't a thing of type check_frontend_t* AFAIK, you would usually translate: typedef int (check_frontend_t*)(void *args, struct dvb_v5_fe_parms *parms); into: alias check_frontend_t = extern(C) int function (void* args, dvb_v5_fe_parms* parms); The problem there is that libdvdv5 defines it as (check_frontend_t) and not (check_frontend_t*). To get around that you can ommit the * in the declaration of dvb_scan_transponder, and then you should be able to pass to it. -- Mike Wey
Re: The reason for SIGSEGV function pointer problem
On 06/07/2017 06:50 PM, Russel Winder via Digitalmars-d-learn wrote: So why isn't a thing of type check_frontend_t*? It's a thing of type `check_frontend_t`, which is a function pointer already. When you add an asterisk, you get a pointer to a function pointer.
Re: The reason for SIGSEGV function pointer problem
On Wednesday, 7 June 2017 at 16:50:26 UTC, Russel Winder wrote: In the constructor of an object to abstract the result of a call to the C library code, the parameter is: check_frontend_t* cf You should remove the pointer here... /Paolo
The reason for SIGSEGV function pointer problem
OK, so I have narrowed down my SIGSEGV problem to having no real idea how to do C function pointers in D code. So I have a callback function that will be called from C library code. It currently has signature: extern(C) int checkFrontend(void* _arguments, dvb_v5_fe_parms* frontendParameters) because of the extern(C) I believe you have to use a type alias in order to specify the type in function definitions. Hence: alias check_frontend_t = extern(C) int function (void* args, dvb_v5_fe_parms* parms); In the constructor of an object to abstract the result of a call to the C library code, the parameter is: check_frontend_t* cf in the creation of the object using the constructor, I am using the argument: However. This gives me a type error: extern (C) int function(void*, dvb_v5_fe_parms*)* cf is not callable using argument type: extern (C) int function(void*, dvb_v5_fe_parms*) all the other arguments/parameters types match exactly, this is the only difference. So why isn't a thing of type check_frontend_t*? -- Russel. = Dr Russel Winder t: +44 20 7585 2200 voip: sip:russel.win...@ekiga.net 41 Buckmaster Roadm: +44 7770 465 077 xmpp: rus...@winder.org.uk London SW11 1EN, UK w: www.russel.org.uk skype: russel_winder
Re: How to overload member function pointer and a regualr member function
On Wednesday, 26 April 2017 at 08:24:08 UTC, Basile B. wrote: On Tuesday, 25 April 2017 at 18:58:58 UTC, Ali Çehreli wrote: On 04/25/2017 11:54 AM, Ali Çehreli wrote: My analysis is wrong because that writefln() is for the bar(float) overload but I still think what you want is achieved. Ali No it's ok, it works. The additional indirection is well avoided: Let's take this module: == #!dmd -release -inline -O module runnable; struct Foo { private void function(int,float) _bar; void bar(float){} pragma(inline, false) void bar(int i, float f){_bar(i,f);} } struct FooInline { private void function(int,float) _bar; void bar(float){} pragma(inline, true) void bar(int i, float f){_bar(i,f);} } void testInlined(ref FooInline foo) { foo.bar(0,0); } void test(ref Foo foo) { foo.bar(0,0); } void main() { import disassembler, std.stdio; disassembler.symbolTable.addModule!runnable; prettyDisasm().writeln; prettyDisasm(, 2).writeln; // dig up to 2 levels, required for the indir. } == and looks at the output: ;--- SUB 00459970h --- ; NAMED: testInlined 00459970h push rbp 00459971h mov rbp, rsp 00459974h sub rsp, 20h 00459978h mov qword ptr [rbp-08h], rdi 0045997Ch xor edi, edi 0045997Eh mov dword ptr [rbp-20h], edi 00459981h movss xmm0, dword ptr [rbp-20h] 00459986h mov rax, qword ptr [rbp-08h] 0045998Ah call qword ptr [rax] 0045998Dh mov rsp, rbp 00459990h pop rbp 00459991h ret ;- ;--- SUB 00459934h --- ; XREFS: [004599A6h] 00459934h push rbp 00459935h mov rbp, rsp 00459938h sub rsp, 10h 0045993Ch mov qword ptr [rbp-08h], rdi 00459940h mov rdi, rsi 00459943h mov rax, qword ptr [rbp-08h] 00459947h call qword ptr [rax] 0045994Ah mov rsp, rbp 0045994Dh pop rbp 0045994Eh ret ;- ;--- SUB 00459994h --- ; NAMED: test 00459994h push rbp 00459995h mov rbp, rsp 00459998h sub rsp, 10h 0045999Ch xor esi, esi 0045999Eh mov dword ptr [rbp-10h], esi 004599A1h movss xmm0, dword ptr [rbp-10h] 004599A6h call 00459934h 004599ABh mov rsp, rbp 004599AEh pop rbp 004599AFh ret ;- - testInlined() contains only the delegate call. (call qword ptr [rax]) - test() contains a call (call 00459934h) which contains the delegate call (call qword ptr [rax]) Actually i've even had to add (pragma inline false) to show the difference since DMD inlined automatically bar() in test(). Guys, you're great! Thanks a lot!
Re: How to overload member function pointer and a regualr member function
On Tuesday, 25 April 2017 at 18:58:58 UTC, Ali Çehreli wrote: On 04/25/2017 11:54 AM, Ali Çehreli wrote: My analysis is wrong because that writefln() is for the bar(float) overload but I still think what you want is achieved. Ali No it's ok, it works. The additional indirection is well avoided: Let's take this module: == #!dmd -release -inline -O module runnable; struct Foo { private void function(int,float) _bar; void bar(float){} pragma(inline, false) void bar(int i, float f){_bar(i,f);} } struct FooInline { private void function(int,float) _bar; void bar(float){} pragma(inline, true) void bar(int i, float f){_bar(i,f);} } void testInlined(ref FooInline foo) { foo.bar(0,0); } void test(ref Foo foo) { foo.bar(0,0); } void main() { import disassembler, std.stdio; disassembler.symbolTable.addModule!runnable; prettyDisasm().writeln; prettyDisasm(, 2).writeln; // dig up to 2 levels, required for the indir. } == and looks at the output: ;--- SUB 00459970h --- ; NAMED: testInlined 00459970h push rbp 00459971h mov rbp, rsp 00459974h sub rsp, 20h 00459978h mov qword ptr [rbp-08h], rdi 0045997Ch xor edi, edi 0045997Eh mov dword ptr [rbp-20h], edi 00459981h movss xmm0, dword ptr [rbp-20h] 00459986h mov rax, qword ptr [rbp-08h] 0045998Ah call qword ptr [rax] 0045998Dh mov rsp, rbp 00459990h pop rbp 00459991h ret ;- ;--- SUB 00459934h --- ; XREFS: [004599A6h] 00459934h push rbp 00459935h mov rbp, rsp 00459938h sub rsp, 10h 0045993Ch mov qword ptr [rbp-08h], rdi 00459940h mov rdi, rsi 00459943h mov rax, qword ptr [rbp-08h] 00459947h call qword ptr [rax] 0045994Ah mov rsp, rbp 0045994Dh pop rbp 0045994Eh ret ;- ;--- SUB 00459994h --- ; NAMED: test 00459994h push rbp 00459995h mov rbp, rsp 00459998h sub rsp, 10h 0045999Ch xor esi, esi 0045999Eh mov dword ptr [rbp-10h], esi 004599A1h movss xmm0, dword ptr [rbp-10h] 004599A6h call 00459934h 004599ABh mov rsp, rbp 004599AEh pop rbp 004599AFh ret ;- - testInlined() contains only the delegate call. (call qword ptr [rax]) - test() contains a call (call 00459934h) which contains the delegate call (call qword ptr [rax]) Actually i've even had to add (pragma inline false) to show the difference since DMD inlined automatically bar() in test().
Re: How to overload member function pointer and a regualr member function
On 04/25/2017 11:54 AM, Ali Çehreli wrote: > _Dmain: > pushRBP > movRBP,RSP > subRSP,010h > movRAX,_D6deneme4funcFifZv@GOTPCREL[RIP] > mov-010h[RBP],RAX > movssXMM0,FLAT:.rodata[00h][RIP] > movss-8[RBP],XMM0 > leaRDX,_TMP0@PC32[RIP] > movEDI,0Eh > movRSI,RDX > movssXMM0,-8[RBP] > call _D3std5stdio17__T8writeflnTaTfZ8writeflnFNfxAafZv@PLT32 > movEAX,02Ah > movssXMM1,FLAT:.rodata[00h][RIP] > movss-4[RBP],XMM1 > movRDI,RAX > movssXMM0,-4[RBP] > callqword ptr -010h[RBP] > xorEAX,EAX > leave > ret > add[RAX],AL > .text._Dmainends > > The call to jumbled writefln() is a direct call inside func(): > > call _D3std5stdio17__T8writeflnTaTfZ8writeflnFNfxAafZv@PLT32 My analysis is wrong because that writefln() is for the bar(float) overload but I still think what you want is achieved. Ali
Re: How to overload member function pointer and a regualr member function
On 04/25/2017 11:28 AM, ParticlePeter wrote: > On Tuesday, 25 April 2017 at 16:27:43 UTC, Basile B. wrote: >> with pragma(inline, true), the function body should be injected at the >> call sites. > > This would not help I fear, the body of the function pointer is unknown > in an external lib. I rather hoped that the compiler "sees" the > parameter forwarding to the fp and is able to directly call it. Best > thing would be for both overloads, but I would not know how to verify this. pragma(inline, true) works because all you need inlined in this case is the body of bar(int, float). The compiler does call the function pointer directly. import std.stdio; struct Foo1 { private void function(int,float) _bar; void bar(float f) { pragma(inline, true); writefln("Called with %s", f); } void bar(int i, float f) { pragma(inline, true); _bar(i,f); } } void func(int i, float f) { writefln("Called with %s and %s", i, f); } void main() { auto f = Foo1(); f.bar(1.5); f.bar(42, 2.5); } Compile with -inline (and perhaps with -O): dmd -inline deneme.d Generate the disassembly with obj2asm that comes with dmd (or with any other disassembly tool): obj2asm deneme.o > deneme.asm You can open deneme.asm in an editor and search for function "_Dmain:" in it. Here is what my dmd 2.074 produced: _Dmain: pushRBP mov RBP,RSP sub RSP,010h mov RAX,_D6deneme4funcFifZv@GOTPCREL[RIP] mov -010h[RBP],RAX movss XMM0,FLAT:.rodata[00h][RIP] movss -8[RBP],XMM0 lea RDX,_TMP0@PC32[RIP] mov EDI,0Eh mov RSI,RDX movss XMM0,-8[RBP] call _D3std5stdio17__T8writeflnTaTfZ8writeflnFNfxAafZv@PLT32 mov EAX,02Ah movss XMM1,FLAT:.rodata[00h][RIP] movss -4[RBP],XMM1 mov RDI,RAX movss XMM0,-4[RBP] callqword ptr -010h[RBP] xor EAX,EAX leave ret add [RAX],AL .text._Dmainends The call to jumbled writefln() is a direct call inside func(): call _D3std5stdio17__T8writeflnTaTfZ8writeflnFNfxAafZv@PLT32 So, you're good... :) Ali
Re: How to overload member function pointer and a regualr member function
On Tuesday, 25 April 2017 at 16:27:43 UTC, Basile B. wrote: On Tuesday, 25 April 2017 at 15:43:48 UTC, ParticlePeter wrote: On Tuesday, 25 April 2017 at 09:50:14 UTC, Basile B. wrote: On Monday, 24 April 2017 at 16:46:21 UTC, ParticlePeter wrote: Thanks for your reply, but that's what I would like to avoid, the additional indirection to call the function pointer with the original argument count. Oops, i can believe i didn't read the last part of your question. Do you have any idea about the likelihood of the compiler removing this indirection as an optimizations? with pragma(inline, true), the function body should be injected at the call sites. This would not help I fear, the body of the function pointer is unknown in an external lib. I rather hoped that the compiler "sees" the parameter forwarding to the fp and is able to directly call it. Best thing would be for both overloads, but I would not know how to verify this.
Re: How to overload member function pointer and a regualr member function
On Tuesday, 25 April 2017 at 09:50:14 UTC, Basile B. wrote: On Monday, 24 April 2017 at 16:46:21 UTC, ParticlePeter wrote: I would like to have this kind of struct: struct Foo { private int i; void function( int i, float f ) bar; // will be defined at runtime void bar( float f ) { bar( i, f ); } } [...] How else can I get the required behavior? Like this: struct Foo1 { private void function(int,float) _bar; void bar(float){} void bar(int i, float f){_bar(i,f);} } Thanks for your reply, but that's what I would like to avoid, the additional indirection to call the function pointer with the original argument count. Do you have any idea about the likelihood of the compiler removing this indirection as an optimizations?
Re: How to overload member function pointer and a regualr member function
On Monday, 24 April 2017 at 16:46:21 UTC, ParticlePeter wrote: I would like to have this kind of struct: struct Foo { private int i; void function( int i, float f ) bar; // will be defined at runtime void bar( float f ) { bar( i, f ); } } [...] How else can I get the required behavior? Like this: struct Foo1 { private void function(int,float) _bar; void bar(float){} void bar(int i, float f){_bar(i,f);} } Or like this: struct Foo2 { private void function(int,float) _bar; void bar(float) {} void function(int,float) bar() {return _bar;} } First solution looks better: (new Foo2).bar()(0,0f) // less good (new Foo1).bar(0,0f) // better
How to overload member function pointer and a regualr member function
I would like to have this kind of struct: struct Foo { private int i; void function( int i, float f ) bar; // will be defined at runtime void bar( float f ) { bar( i, f ); } } But apparently the function pointer and the member function cannot have the same name: Error: function main.Foo.bar conflicts with variable main.Foo.bar ... I tried with an inner struct: struct Foo { private int i; void function( int i, float f ) bar; // will be defined at runtime private struct Inner { void bar( float f ) { bar( i, f ); } } Inner inner; } But this time I get following error: Error: need 'this' for 'i' of type 'int' What does this message tell me? Should the inner struct not be able to access Foo.i? How else can I get the required behavior? I would prefer to avoid another indirection like this: struct Foo { private int i; void function( int i, float f ) bar; // will be defined at runtime void baz( float f ) { bar( i, f ); } void baz( int ii, float f ) { bar( ii, f ); } }
Re: Function pointer pitfalls
On Tuesday, 14 March 2017 at 19:14:34 UTC, H. S. Teoh wrote: On Tue, Mar 14, 2017 at 06:59:58PM +, Inquie via Digitalmars-d-learn wrote: [...] [...] > [...] [...] [...] [...] Keep in mind, though, that the above creates a function pointer with the same signature as the member function, but you may not be able to assign a member pointer to it because it lacks object context. To wit: [...] Yeah, I don't think I'll run in to that problem since I'm constructing the function ahead of time and only need the declaration but we'll see. Thanks again.
Re: Function pointer pitfalls
On Tue, Mar 14, 2017 at 06:59:58PM +, Inquie via Digitalmars-d-learn wrote: > On Tuesday, 14 March 2017 at 17:42:34 UTC, H. S. Teoh wrote: [...] > > struct X { > > int method(float x) { return 0; } > > } > > > > typeof() membptr; > > pragma(msg, typeof(membptr)); // prints `int function(float x)` > > > > If you need to refer to the function pointer type frequently, you > > could alias it to something easier to type; > > > > alias FuncPtr = typeof(); > > FuncPtr membptr; [...] > Thanks, that will work. In C++ there were issues with pointers and one > would have to properly group the function name or some thing like > that. Your suggestion avoids all that. [...] Keep in mind, though, that the above creates a function pointer with the same signature as the member function, but you may not be able to assign a member pointer to it because it lacks object context. To wit: struct X { int method(float x) { return 0; } } X x; alias FuncPtr = typeof(); FuncPtr fp; alias MembPtr = typeof(); MembPtr mp; mp = // OK //fp = // NG: cannot implicitly convert expression () of type int delegate(float z) to int function(float z) - is a delegate because it encapsulates the instance of X that it should be invoked with, so you can't assign it to a func ptr without that context (since method() can't be called without an instance of X). T -- Question authority. Don't ask why, just do it.
Re: Function pointer pitfalls
On Tuesday, 14 March 2017 at 17:42:34 UTC, H. S. Teoh wrote: On Tue, Mar 14, 2017 at 05:05:10PM +, Inquie via Digitalmars-d-learn wrote: I am generating member function pointers using the declaration specified from a standard member function. The standard member function is a valid D function that could use any types. Is there any pitfalls like there are in C++ from generating a function pointer from them? e.g., X foo(A,B,C) @R @S @T -> X function(A,B,C) @R @S @T fooptr; In my case, there are no attributes, so that might ease the burden. e.g., a template that converts a member function declaration. ToFunctionPtr!("X foo(A,B,C) @R @S @T)", fooptr) or ToFunctionPtr!(foo, fooptr) gives function pointer declaration who's declaration is the same as foo. Not 100% sure what exactly you mean... but I'm guessing you have some aggregate X with some member function method(), and you want to get a function pointer from that? Perhaps something like this? struct X { int method(float x) { return 0; } } typeof() membptr; pragma(msg, typeof(membptr)); // prints `int function(float x)` If you need to refer to the function pointer type frequently, you could alias it to something easier to type; alias FuncPtr = typeof(); FuncPtr membptr; T Thanks, that will work. In C++ there were issues with pointers and one would have to properly group the function name or some thing like that. Your suggestion avoids all that.
Re: Function pointer pitfalls
On Tue, Mar 14, 2017 at 05:05:10PM +, Inquie via Digitalmars-d-learn wrote: > I am generating member function pointers using the declaration > specified from a standard member function. The standard member > function is a valid D function that could use any types. > > Is there any pitfalls like there are in C++ from generating a function > pointer from them? > > e.g., > > X foo(A,B,C) @R @S @T -> X function(A,B,C) @R @S @T fooptr; > > In my case, there are no attributes, so that might ease the burden. > > e.g., a template that converts a member function declaration. > > ToFunctionPtr!("X foo(A,B,C) @R @S @T)", fooptr) > > or > > ToFunctionPtr!(foo, fooptr) > > gives function pointer declaration who's declaration is the same as > foo. Not 100% sure what exactly you mean... but I'm guessing you have some aggregate X with some member function method(), and you want to get a function pointer from that? Perhaps something like this? struct X { int method(float x) { return 0; } } typeof() membptr; pragma(msg, typeof(membptr)); // prints `int function(float x)` If you need to refer to the function pointer type frequently, you could alias it to something easier to type; alias FuncPtr = typeof(); FuncPtr membptr; T -- Turning your clock 15 minutes ahead won't cure lateness---you're just making time go faster!
Function pointer pitfalls
I am generating member function pointers using the declaration specified from a standard member function. The standard member function is a valid D function that could use any types. Is there any pitfalls like there are in C++ from generating a function pointer from them? e.g., X foo(A,B,C) @R @S @T -> X function(A,B,C) @R @S @T fooptr; In my case, there are no attributes, so that might ease the burden. e.g., a template that converts a member function declaration. ToFunctionPtr!("X foo(A,B,C) @R @S @T)", fooptr) or ToFunctionPtr!(foo, fooptr) gives function pointer declaration who's declaration is the same as foo.
Re: How can I implement this in D: a variant array of varying function pointer types (diff number of args or types)
On Tuesday, 17 January 2017 at 10:49:14 UTC, Enjoys Math wrote: Z add(Z...)(Z a...) { return a + b; } func[] operatorPool = [!int]; Variant library isn't liking that. Removing & causes another error. Essentially I want a pool of all operators that I define, but these operators can be of differing types (which I should be able to programatically grab), and different N-aryness. Try using `variantArray` from std.variant. see https://dlang.org/phobos/std_variant.html#.variantArray
Re: How can I implement this in D: a variant array of varying function pointer types (diff number of args or types)
On Tuesday, 17 January 2017 at 10:49:14 UTC, Enjoys Math wrote: Z add(Z...)(Z a...) { return a + b; } func[] operatorPool = [!int]; Variant library isn't liking that. Removing & causes another error. Essentially I want a pool of all operators that I define, but these operators can be of differing types (which I should be able to programatically grab), and different N-aryness. func? I mean std.variant.Variant there.
How can I implement this in D: a variant array of varying function pointer types (diff number of args or types)
Z add(Z...)(Z a...) { return a + b; } func[] operatorPool = [!int]; Variant library isn't liking that. Removing & causes another error. Essentially I want a pool of all operators that I define, but these operators can be of differing types (which I should be able to programatically grab), and different N-aryness.
Re: Cryptic C function pointer for conversion
On Saturday, 17 December 2016 at 15:15:26 UTC, data pulverizer wrote: Does this mean that you can translate C code to D natively? I am currently only aware of the dstep package. It may not help you, but something I've done in the past is use Swig to create a Common Lisp interface. It translates the C to Common Lisp. That is generally much easier for me to understand.
Re: Cryptic C function pointer for conversion
p.s.: that means that i didn't really *decoded* that declaration, just brute-forced someting that c++ compiler happily accepts. so take it with a grain of salt. ;-)
Re: Cryptic C function pointer for conversion
On Saturday, 17 December 2016 at 14:06:07 UTC, ketmar wrote: On Saturday, 17 December 2016 at 13:39:27 UTC, data pulverizer wrote: that is what it means, in D: //void (*(*xDlSym)(sqlite3_vfs*,void*, const char *zSymbol))(void); struct sqlite3_vfs {} extern(C) { alias RetRes = void function (); alias DeclType = RetRes function (sqlite3_vfs *a,void *b, const char *zSymbol); DeclType xDlSym; void zoo (void) {} auto goo (sqlite3_vfs *a,void *b, const char *zSymbol) { return } } void main () { xDlSym = } at least that is what i managed to decode, fed to C(++) compiler and translate to D. p.s. I confirmed your interpretation on stackoverflow: http://stackoverflow.com/questions/8722817/syntax-for-a-pointer-to-a-function-returning-a-function-pointer-in-c
Re: Cryptic C function pointer for conversion
On Saturday, 17 December 2016 at 15:15:26 UTC, data pulverizer wrote: Does this mean that you can translate C code to D natively? I am currently only aware of the dstep package. with my head and bare hands. well, armed with some regular expressions. did you seen some of my "port" announcements? they all done manually. it's not that hard, mostly search-and-replace. also, i did used c++ 'cause it has `auto` feature, so i pasted your declaration, and then played with c++ and -Wall until it silenced. actually, void zoo (void) {} auto goo (sqlite3_vfs *a,void *b, const char *zSymbol) { return } was taken verbatim from c++. as you can see, it even has `(void)`, which is forbidden in D (but allowed in my dmd fork ;-).
Re: Cryptic C function pointer for conversion
On Saturday, 17 December 2016 at 14:06:07 UTC, ketmar wrote: that is what it means, in D: //void (*(*xDlSym)(sqlite3_vfs*,void*, const char *zSymbol))(void); struct sqlite3_vfs {} extern(C) { alias RetRes = void function (); alias DeclType = RetRes function (sqlite3_vfs *a,void *b, const char *zSymbol); ... } Thanks ketmar, I guess that this means I got it the other way round the function pointer that is returned is the function that takes in and returns void. at least that is what i managed to decode, fed to C(++) compiler and translate to D. Does this mean that you can translate C code to D natively? I am currently only aware of the dstep package.
Re: Cryptic C function pointer for conversion
On Saturday, 17 December 2016 at 13:39:27 UTC, data pulverizer wrote: that is what it means, in D: //void (*(*xDlSym)(sqlite3_vfs*,void*, const char *zSymbol))(void); struct sqlite3_vfs {} extern(C) { alias RetRes = void function (); alias DeclType = RetRes function (sqlite3_vfs *a,void *b, const char *zSymbol); DeclType xDlSym; void zoo (void) {} auto goo (sqlite3_vfs *a,void *b, const char *zSymbol) { return } } void main () { xDlSym = } at least that is what i managed to decode, fed to C(++) compiler and translate to D.
Cryptic C function pointer for conversion
I have come across a function pointer in C that I am attempting to convert, and am not sure what the current interpretation is: ``` \\ The C Code: void (*(*xDlSym)(sqlite3_vfs*,void*, const char *zSymbol))(void); ``` The best I can tell is that this is a function pointer that returns a function that returns void and the correct translation to D is: ``` alias void function(sqlite3_vfs*,void*, const char *zSymbol) ptr; ptr* function() xDlSym; ``` I've never seen a construction like this before so my interpretation might be wrong!
Re: Modify Function Pointer to Take Additional Parameters
On Friday, 19 February 2016 at 22:34:48 UTC, Chris Wright wrote: I tested this a fair bit today, and I haven't been able to do any of the nefarious things I expected to be able to do. No overwriting variables in the caller's scope, no smashing stack pointers, etc. I was surprised by this result, but in retrospect, it's relatively obvious. The caller pushes variables onto the stack and sets the stack pointer for the callee. It wouldn't send a stack pointer that pointed into its own stack frame. Thanks for taking the time to test. The more I've thought about it, the more I wonder if there should be a restriction so that casts of function pointers/delegate maintain the same number of parameters. Even though you haven't been able to do nefarious things, it's giving a completely wrong answer than you would expect. The result of the answer might cause bad things to happen in a program. Further, to even understand what's going wrong you have to understand how the compiler is generating assembly. I've been using D for like a year or so, and I would never have been able to figure out the reason by myself. Or at least in safe code you shouldn't be able to do this.
Re: Modify Function Pointer to Take Additional Parameters
On Fri, 19 Feb 2016 21:57:46 +, Yuxuan Shui wrote: > I don't think it's safe to convert between function pointer with > different number of arguments... It's possible to mess up the stack > frame. I tested this a fair bit today, and I haven't been able to do any of the nefarious things I expected to be able to do. No overwriting variables in the caller's scope, no smashing stack pointers, etc. I was surprised by this result, but in retrospect, it's relatively obvious. The caller pushes variables onto the stack and sets the stack pointer for the callee. It wouldn't send a stack pointer that pointed into its own stack frame.
Re: Modify Function Pointer to Take Additional Parameters
On Friday, 19 February 2016 at 22:07:25 UTC, Chris Wright wrote: If you want to cast function pointers successfully, you have to know the D calling convention. [snip] I figured there was an explanation. Definitely "here be dragons" territory. I hope I can figure out a better solution, but the behavior I'm trying to get is really just a nice to have.
Re: Modify Function Pointer to Take Additional Parameters
On Fri, 19 Feb 2016 20:45:23 +, jmh530 wrote: > I tried to use a cast (below) to modify the function pointer, but it is > printing the second number instead of the first. I find this behavior > strange... If you want to cast function pointers successfully, you have to know the D calling convention. See: https://dlang.org/spec/abi.html Notably: "The last parameter is passed in EAX [a CPU register] rather than being pushed on the stack". So foo expected an argument in EAX, and it dealt with that. Calling foo_ pushes '1' onto the stack, sets EAX to '200', and then jumps to the function address. (But note also: "The callee cleans the stack." So if you pass, say, a struct that has a destructor instead of an integer, that means the struct destructor won't be called. I was a little surprised that the stack pointer is correctly restored.) If you had more arguments, you'd find similar results -- the last argument always goes to EAX, previous arguments are pushed on the stack in order, so you're always ignoring a prefix of the arguments. But it's a byte-wise prefix, so if you change the types, you'll see more significant changes. Casting function pointers is "here be dragons" territory. Unfortunately, it's got the same syntax as routine stuff like integer truncation and class casts, so it looks deceptively safe.
Re: Modify Function Pointer to Take Additional Parameters
On Friday, 19 February 2016 at 20:45:23 UTC, jmh530 wrote: On Friday, 19 February 2016 at 15:00:51 UTC, jmh530 wrote: This works. But when I re-write foo to take that into account as in below, I get an error that I can't implicitly convert int function(int x) to int function(int x, int y). I don't think I had looked at what you had done carefully enough. Basically, you just define a new function and take a function pointer of that. That might be a brute force solution. I tried to use a cast (below) to modify the function pointer, but it is printing the second number instead of the first. I find this behavior strange... int foo(int x) { return x; } void main() { import std.stdio : writeln; auto foo_ = cast(int function(int x, int y)) writeln(foo_(1, 200)); //prints 200 } I don't think it's safe to convert between function pointer with different number of arguments... It's possible to mess up the stack frame. Also '(int x, int y)=>f(x)' is clearly a delegate because it refers to local variable 'f', you can't just cast it to 'int function(int, int)'.
Re: Modify Function Pointer to Take Additional Parameters
On Friday, 19 February 2016 at 15:00:51 UTC, jmh530 wrote: This works. But when I re-write foo to take that into account as in below, I get an error that I can't implicitly convert int function(int x) to int function(int x, int y). I don't think I had looked at what you had done carefully enough. Basically, you just define a new function and take a function pointer of that. That might be a brute force solution. I tried to use a cast (below) to modify the function pointer, but it is printing the second number instead of the first. I find this behavior strange... int foo(int x) { return x; } void main() { import std.stdio : writeln; auto foo_ = cast(int function(int x, int y)) writeln(foo_(1, 200)); //prints 200 }
Re: Modify Function Pointer to Take Additional Parameters
On Friday, 19 February 2016 at 14:21:26 UTC, Kagamin wrote: int bar(int x) { return x; } int baz(int x, int y) { return bar(x); } void main() { import std.stdio : writeln; int function(int x, int y) foo_bar = writeln(foo_bar(1, 2)); } This works. But when I re-write foo to take that into account as in below, I get an error that I can't implicitly convert int function(int x) to int function(int x, int y). auto foo(T)(T f) { static if (is(T == fp2)) { return f; } else static if (is(T == fp1)) { int function(int x, int y) f_ = f; return f_; } else { return 0; } }
Re: Modify Function Pointer to Take Additional Parameters
On Friday, 19 February 2016 at 11:26:56 UTC, Nicholas Wilson wrote: Like alias fp1 = int function(int x); alias fp2 = int function(int x, int y); auto foo(T)(T f) { static if (is(T == fp2)) return f; else static if (is(T == fp1)) { return int function(int x, int y) => f(x); } else return 0; } ? This code doesn't compile for me. I have to adjust it to return function int(int x, int y) => f(x); and then it complains that it's a delegate.
Re: Modify Function Pointer to Take Additional Parameters
On Friday, 19 February 2016 at 05:41:01 UTC, jmh530 wrote: void main() { import std.stdio : writeln; auto foo_bar = foo(); writeln(qux(1, 2, foo_bar)); //compiler error writeln(qux(1, 2, )); } int bar(int x) { return x; } int baz(int x, int y) { return bar(x); } void main() { import std.stdio : writeln; int function(int x, int y) foo_bar = writeln(foo_bar(1, 2)); }
Re: Modify Function Pointer to Take Additional Parameters
On Friday, 19 February 2016 at 05:41:01 UTC, jmh530 wrote: I'm trying to write a function that will adjust the parameters of a function pointer. I think the problem is that it defaults to a delegate not that it cannot be one does clarifying this to the compiler work Like alias fp1 = int function(int x); alias fp2 = int function(int x, int y); auto foo(T)(T f) { static if (is(T == fp2)) return f; else static if (is(T == fp1)) { return int function(int x, int y) => f(x); } else return 0; } ?
Modify Function Pointer to Take Additional Parameters
I'm trying to write a function that will adjust the parameters of a function pointer. In the code below, my goal is to call the function qux with a variety of different function pointers (in the actual application, I don't have the ability to modify qux). I created a function foo that I thought would adjust it properly. The problem is that the foo function converts the function pointer into a delegate. I was able to get something that works in this simple example by introducing a delegate alias and an alternate definition of qux that takes a delegate. However, in my actual application, I can't modify what the equivalent of qux would take as parameters. So I was just curious if there was any other alternative. alias fp1 = int function(int x); alias fp2 = int function(int x, int y); auto foo(T)(T f) { static if (is(T == fp2)) return f; else static if (is(T == fp1)) { return (int x, int y) => f(x); } else return 0; } int bar(int x) { return x; } int baz(int x, int y) { return x + y; } int qux(int x, int y, fp2 f) { return f(x, y); } void main() { import std.stdio : writeln; auto foo_bar = foo(); writeln(qux(1, 2, foo_bar)); //compiler error writeln(qux(1, 2, )); }
Re: LNK2019 error from using a function pointer to core.bitop functions?
On Friday, 17 July 2015 at 15:47:39 UTC, Roland Hadinger wrote: Otherwise, I'd use templates and an alias. Maybe this will result in faster code: bool opIndexAssign(bool value, size_t[2] inds) { void impl(bool b)(size_t[2] inds) { static if(b) alias btx = bts; else alias btx = btr; // code from opIndexAssign goes here... // for (size_t i = startBitInd; ... } if( value ) impl!true(inds); else impl!false(inds); return value; // oops }
Re: LNK2019 error from using a function pointer to core.bitop functions?
On Thursday, 16 July 2015 at 03:24:54 UTC, Matthew Gamble wrote: This member function of my struct uses a function pointer btx. When the line declaring the function pointer is present I get a LNK2019 error: unresolved external symbol. Just guessing, probably because bts and btr are intrinsics? If performance is not that important, you can always do this at the start of your opIndexAssign method: static int bts(size_t* p, size_t bitnum) { return .bts(p, bitnum); } static int btr(size_t* p, size_t bitnum) { return .btr(p, bitnum); } int function(size_t*, size_t) btx = (value) ? bts : btr; Otherwise, I'd use templates and an alias. Maybe this will result in faster code: bool opIndexAssign(bool value, size_t[2] inds) { void impl(bool b)(size_t[2] inds) { static if(b) alias btx = bts; else alias btx = btr; // code from opIndexAssign goes here... // for (size_t i = startBitInd; ... } if( value ) impl!true(inds); else impl!false(inds); }
Re: LNK2019 error from using a function pointer to core.bitop functions?
On Friday, 17 July 2015 at 15:49:46 UTC, Roland Hadinger wrote: On Friday, 17 July 2015 at 15:47:39 UTC, Roland Hadinger wrote: Otherwise, I'd use templates and an alias. Maybe this will result in faster code: bool opIndexAssign(bool value, size_t[2] inds) { void impl(bool b)(size_t[2] inds) { static if(b) alias btx = bts; else alias btx = btr; // code from opIndexAssign goes here... // for (size_t i = startBitInd; ... } if( value ) impl!true(inds); else impl!false(inds); return value; // oops } Roland, both of your solutions work perfectly. Thank you. You brought up the issue of performance. Performance may be an issue for certain use-cases when the function is called many times and the values of inds[1] - inds[0] is small (e.g less than 257). In these cases at least half the work in the function will be done with bts/btr. However, for larger ranges there is an optimization (not shown) that eliminates the need to call bts/btr in the middle region of the range. Why do you think the second solution would be faster than the first? And do you also think that the rolled out version replicating the code in the if and else blocks replacing bts with btr would be even faster since it eliminates the need for any additional function call? I guess I'll have to profile all three versions when my program matures enough be used with a big data example. Sorry for all the questions. I really appreciate your help. Best, Matt
LNK2019 error from using a function pointer to core.bitop functions?
This member function of my struct uses a function pointer btx. When the line declaring the function pointer is present I get a LNK2019 error: unresolved external symbol. bool opIndexAssign(bool value, size_t[2] inds) { int function(size_t*, size_t) btx = (value) ? bts : btr; // error is here // other stuff here for (size_t i = startBitInd; i startWordBitDone; ++i) btx(bitArray[startWord], i); // other stuff here if (startWord != stopWord) for (size_t i = 0; i stopBitInd; ++i) btx(bitArray[stopWord], i); return value; } However, when I don't use the function pointer and instead call bts directly (as outlined below, the program compiles and links just fine. bool opIndexAssign(bool value, size_t[2] inds) { // other stuff here for (size_t i = startBitInd; i startWordBitDone; ++i) bts(bitArray[startWord], i); // other stuff here if (startWord != stopWord) for (size_t i = 0; i stopBitInd; ++i) bts(bitArray[stopWord], i); return value; } Any ideas how to fix this behavior? I was trying to use the function pointer so I wouldn't need to write essentially the same code block replacing bts with btr in if and else blocks Any help would be appreciated. Thanks
Re: Function pointer array slice?
On Sat, 11 Jul 2015 09:54:40 +, tcak wrote: On Saturday, 11 July 2015 at 09:30:43 UTC, Tofu Ninja wrote: So simple syntax question, how do I make an array slice of function pointers? I just have no idea where to put the [] on something like void function() nothrow pure @nogc @safe arrayName; Or should I just alias it and make an array of the alias? alias f = void function() nothrow pure @nogc @safe; f[] arrayName; Alias is the correct way IMO. yet void function() nothrow pure @nogc @safe [2]arrayName; is perfectly fine too. signature.asc Description: PGP signature
Function pointer array slice?
So simple syntax question, how do I make an array slice of function pointers? I just have no idea where to put the [] on something like void function() nothrow pure @nogc @safe arrayName; Or should I just alias it and make an array of the alias? alias f = void function() nothrow pure @nogc @safe; f[] arrayName;
Re: Function pointer array slice?
On Saturday, 11 July 2015 at 10:54:45 UTC, ketmar wrote: On Sat, 11 Jul 2015 09:54:40 +, tcak wrote: On Saturday, 11 July 2015 at 09:30:43 UTC, Tofu Ninja wrote: So simple syntax question, how do I make an array slice of function pointers? I just have no idea where to put the [] on something like void function() nothrow pure @nogc @safe arrayName; Or should I just alias it and make an array of the alias? alias f = void function() nothrow pure @nogc @safe; f[] arrayName; Alias is the correct way IMO. yet void function() nothrow pure @nogc @safe [2]arrayName; is perfectly fine too. Ahh, guess that makes sense, I kept trying to put the [] over near function()... looks weird as hell though. I really wish you could put types in parens, I feel like things like this would make way more sense if you could write (void function() nothrow pure @nogc @safe)[] arrayName; Reading it, that makes wayyy more sense to me, to bad I can't write this...
Re: Function pointer array slice?
On Saturday, 11 July 2015 at 09:30:43 UTC, Tofu Ninja wrote: So simple syntax question, how do I make an array slice of function pointers? I just have no idea where to put the [] on something like void function() nothrow pure @nogc @safe arrayName; Or should I just alias it and make an array of the alias? alias f = void function() nothrow pure @nogc @safe; f[] arrayName; Alias is the correct way IMO.
Re: Function pointer array slice?
On Sat, 11 Jul 2015 11:37:03 +, Tofu Ninja wrote: void function() nothrow pure @nogc @safe [2]arrayName; is perfectly fine too. Ahh, guess that makes sense, I kept trying to put the [] over near function()... attributes are the parts of the type. and the rule is really simple: put [] array declaration immediately left of the array name. ;-) looks weird as hell though. I really wish you could put types in parens, I feel like things like this would make way more sense if you could write (void function() nothrow pure @nogc @safe)[] arrayName; Reading it, that makes wayyy more sense to me, to bad I can't write this... i agree, this is somewhat easier to read. but it requires grammar changes, i believe, and dunno what consequences that may have. yet it may worth filling a ER. signature.asc Description: PGP signature
Re: Function name from function pointer
On Saturday, 11 April 2015 at 19:08:50 UTC, Marco Leise wrote: Am Sat, 11 Apr 2015 18:28:35 + schrieb Paul D Anderson claude.re...@msnmail.com: Is there a way to return the name of a function (a string) from a pointer to that function? Function pointer example from D Reference: --- int function() fp; void test() { static int a = 7; static int foo() { return a + 3; } fp = foo; } void bar() { test(); int i = fp(); // i is set to 10 } --- Can I get foo from fp? Paul Nope, that would require that fp not only contains a pointer to the function but also a pointer to the name. That's not how it works. But continuing that thought, you could add the function's name as an additional variable and set that every time you set fp. Okay, thanks, I can see that. Paul
Re: Function name from function pointer
Am Sat, 11 Apr 2015 18:28:35 + schrieb Paul D Anderson claude.re...@msnmail.com: Is there a way to return the name of a function (a string) from a pointer to that function? Function pointer example from D Reference: --- int function() fp; void test() { static int a = 7; static int foo() { return a + 3; } fp = foo; } void bar() { test(); int i = fp(); // i is set to 10 } --- Can I get foo from fp? Paul Nope, that would require that fp not only contains a pointer to the function but also a pointer to the name. That's not how it works. But continuing that thought, you could add the function's name as an additional variable and set that every time you set fp. -- Marco
Re: Function name from function pointer
Paul D Anderson: Is there a way to return the name of a function (a string) from a pointer to that function? Perhaps creating a string[void*] AA and initializing with all the function pointers you care about. Bye, bearophile
Function name from function pointer
Is there a way to return the name of a function (a string) from a pointer to that function? Function pointer example from D Reference: --- int function() fp; void test() { static int a = 7; static int foo() { return a + 3; } fp = foo; } void bar() { test(); int i = fp(); // i is set to 10 } --- Can I get foo from fp? Paul
Re: Function pointer to member function.
On Thursday, 17 October 2013 at 03:21:38 UTC, Chris Cain wrote: On Thursday, 17 October 2013 at 01:17:21 UTC, TheFlyingFiddle wrote: I would like to get access to a member function pointer. Taking the this* as the first argument. ...snip... How should i implement getFP above? Is it even possible? Well, it's certainly possible. If you were to do this: ``` delegate void(int) dg = a.bar; dg(1); ``` then you'd see the behavior you're looking for. Basically the class reference is stored in dg.ptr and the function is in dg.funcptr. With that in mind, I whipped this up: ``` import std.stdio; class Foo { char c; this() { c = 'a'; } this(char _c) { c = _c; } void bar(int i) { writeln(i = , i, c = , c); } } import std.traits; //ParentOf!S is pseudocode representing __traits(parent, S) //ReturnType!S function(ParentOf!S, ParameterTypeTuple!S) auto getFP(alias S)() if(isSomeFunction!S) { mixin(alias Parent = ~ __traits(parent, S).stringof ~ ;); return (Parent r, ParameterTypeTuple!S t) { ReturnType!S delegate(ParameterTypeTuple!S) dg; dg.funcptr = S; dg.ptr = cast(void*) r; return dg(t); }; } void main() { Foo a = new Foo(); Foo b = new Foo('b'); auto fp = getFP!(Foo.bar); fp(a, 1); fp(b, 2); } ``` Now one thing to note is that I'm not confident it's bug-free. It does work in this test case, but I couldn't use __traits(parent, S) as a type, so I used a mixin to kind of force it to work. So I'm not fully sure whether it will work in all cases, but if someone else has some improvements, that's fine. Another thing: I didn't spend too much time on the template constraint. isSomeFunction is almost certainly too permissive. I just threw it together and I haven't coded in D for a while. I hope this helped! Thanks, this works well for my needs.
Function pointer to member function.
I would like to get access to a member function pointer. Taking the this* as the first argument. class Foo { void bar(int a) { //do something awesome } } unittest { Foo a = new Foo(); Foo b = new Foo(); auto fp = getFP!(Foo.bar); fp(a, 1); //Basically calls a.foo(1) fp(b, 1); //Basically calls b.foo(1) } How should i implement getFP above? Is it even possible?
Re: Function pointer to member function.
On Thursday, 17 October 2013 at 01:17:21 UTC, TheFlyingFiddle wrote: I would like to get access to a member function pointer. Taking the this* as the first argument. ...snip... How should i implement getFP above? Is it even possible? Well, it's certainly possible. If you were to do this: ``` delegate void(int) dg = a.bar; dg(1); ``` then you'd see the behavior you're looking for. Basically the class reference is stored in dg.ptr and the function is in dg.funcptr. With that in mind, I whipped this up: ``` import std.stdio; class Foo { char c; this() { c = 'a'; } this(char _c) { c = _c; } void bar(int i) { writeln(i = , i, c = , c); } } import std.traits; //ParentOf!S is pseudocode representing __traits(parent, S) //ReturnType!S function(ParentOf!S, ParameterTypeTuple!S) auto getFP(alias S)() if(isSomeFunction!S) { mixin(alias Parent = ~ __traits(parent, S).stringof ~ ;); return (Parent r, ParameterTypeTuple!S t) { ReturnType!S delegate(ParameterTypeTuple!S) dg; dg.funcptr = S; dg.ptr = cast(void*) r; return dg(t); }; } void main() { Foo a = new Foo(); Foo b = new Foo('b'); auto fp = getFP!(Foo.bar); fp(a, 1); fp(b, 2); } ``` Now one thing to note is that I'm not confident it's bug-free. It does work in this test case, but I couldn't use __traits(parent, S) as a type, so I used a mixin to kind of force it to work. So I'm not fully sure whether it will work in all cases, but if someone else has some improvements, that's fine. Another thing: I didn't spend too much time on the template constraint. isSomeFunction is almost certainly too permissive. I just threw it together and I haven't coded in D for a while. I hope this helped!
Re: Call a function with a function pointer
Am 10.10.2013 17:45, schrieb Namespace: On Thursday, 10 October 2013 at 15:15:45 UTC, bearophile wrote: Namespace: You mean like this? void foo(T)(extern(C) void function(T*) func) { } That prints: Error: basic type expected, not extern In 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 /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*) 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 Thaut
Re: Call a function with a function pointer
On 10/13/13 16:43, Benjamin Thaut wrote: Am 10.10.2013 17:45, schrieb Namespace: On Thursday, 10 October 2013 at 15:15:45 UTC, bearophile wrote: Namespace: You mean like this? void foo(T)(extern(C) void function(T*) func) { } That prints: Error: basic type expected, not extern In 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 /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*) I found a possible workaround. Its ugly as hell, but at least it works until the bugs are fixed. 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; artur