www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - How can a function pointer required to be extern(C)?

reply rempas <rempas tutanota.com> writes:
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(&this.thread_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(&this.thread_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?
Apr 12 2023
parent reply "H. S. Teoh" <hsteoh qfbox.info> writes:
On Wed, Apr 12, 2023 at 08:23:51PM +0000, 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(&this.thread_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(&this.thread_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(&abc); pragma(msg, typeof(abc)); pragma(msg, typeof(&abc)); //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.
Apr 12 2023
next sibling parent reply John Chapman <johnch_atms hotmail.com> writes:
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(&abc);
You can also express it like this: ```d extern(C) alias FuncPtr = void* function(void*); ```
Apr 12 2023
parent rempas <rempas tutanota.com> writes:
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!
Apr 13 2023
prev sibling parent rempas <rempas tutanota.com> writes:
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(&abc);
 pragma(msg, typeof(abc));
 pragma(msg, typeof(&abc));

 //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!
Apr 13 2023