Thread overview
How can a function pointer required to be extern(C)?
Apr 12, 2023
rempas
Apr 12, 2023
H. S. Teoh
Apr 12, 2023
John Chapman
Apr 13, 2023
rempas
Apr 13, 2023
rempas
April 12, 2023

Sorry if the title doesn't make any sense, let me explain. So, I do have the following code that does not compile:

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:

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?

April 12, 2023
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.
April 12, 2023

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:

extern(C) alias FuncPtr = void* function(void*);
April 13, 2023

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!

April 13, 2023

On Wednesday, 12 April 2023 at 21:00:04 UTC, John Chapman wrote:

>

You can also express it like this:

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!