Thread overview
Why I get delegate when passing address of function?
Sep 11, 2022
Injeckt
Sep 11, 2022
Mike Parker
Sep 11, 2022
Mike Parker
Sep 11, 2022
Injeckt
Sep 11, 2022
Ali Çehreli
Sep 11, 2022
Ali Çehreli
Sep 11, 2022
Injeckt
September 11, 2022

I have a one class and two modificators, where in "public" function I'm calling CreateThread with address of the ClientThread function which stored in same class, but in "private" modificator.

And i get this error:
Error: cannot pass argument &this.ClientThread of type extern (Windows) uint delegate(void* param) to parameter extern (Windows) uint function(void*) @system.

public:
    void server_init() {
        CreateThread(NULL, 0, &this.ClientThread, cast(PVOID)clientSocket, 0, NULL);
    }

private:
    extern(Windows)
    DWORD ClientThread(PVOID param) {
        this.log("\nHello from thread\n");
        return 0;
    }
September 11, 2022

On Sunday, 11 September 2022 at 09:02:31 UTC, Injeckt wrote:

>

I have a one class and two modificators, where in "public" function I'm calling CreateThread with address of the ClientThread function which stored in same class, but in "private" modificator.

And i get this error:
Error: cannot pass argument &this.ClientThread of type extern (Windows) uint delegate(void* param) to parameter extern (Windows) uint function(void*) @system.

Pointers to non-static member functions always produce a delegate. Otherwise, you wouldn't be able to access the class instance's members.

September 11, 2022

On Sunday, 11 September 2022 at 09:15:11 UTC, Mike Parker wrote:

>

Pointers to non-static member functions always produce a delegate. Otherwise, you wouldn't be able to access the class instance's members.

Reference:

https://dlang.org/spec/function.html#closures

September 11, 2022

On Sunday, 11 September 2022 at 09:29:23 UTC, Mike Parker wrote:

>

On Sunday, 11 September 2022 at 09:15:11 UTC, Mike Parker wrote:

>

Pointers to non-static member functions always produce a delegate. Otherwise, you wouldn't be able to access the class instance's members.

Reference:

https://dlang.org/spec/function.html#closures

And what I should do to pass non-static function? I'm trying get function with .funcptr property, but it still doesn't work.

CreateThread(NULL, 0, this.ClientThread.funcptr, cast(PVOID)clientSocket, 0, NULL);

Error: function _server.Server.ClientThread(void* param) is not callable using argument types (). too few arguments, expected 1, got 0

Is there ways to do that with non-static function or anyway I must make it static?

September 11, 2022
On 9/11/22 02:54, Injeckt wrote:

> And what I should do to pass non-static function?

You can combine your class object with other arguments and your thread function will know how to unwrap your class object to call its member function:

import std.stdio;

// I am not on Windows, so I am making it non-D another way
// Let's assume this is what the library wants from us
alias MyThreadFunc = uint function(void*);

// Let's assume this is what the library provides
extern (C)
void libraryCreateThread(MyThreadFunc func, void* param) {
    writeln("The libraryCreateThread is starting our function");
    func(param);
}

// This is my class
class C {
    string s;

    // This is the function I want to be called
    void myClientThread(void* param) {
        writeln("The desired member function is here");
        writeln("the member: ", s);

        // At this point we know the extra argument shoud be an
        // int (that's why main used one)
        auto arg = *cast(int*)param;
        writeln("the extra argument: ", arg);
    }
}

// We have to play along with what the library wants
// It wants a 'function', so here is one:
// (This could be a static member function)
uint myNonMemberThreadFunc(void* param) {
    writeln("Our function is making the param useful...");

    // See MyThreadArgs below
    auto args = *cast(MyThreadArgs*)param;

    writeln("... and calling our member function");
    args.c.myClientThread(args.extraArg);

    return 0;
}

// This combines a class instance (which is a pointer behind the scene)
// and any other argument
struct MyThreadArgs {
    C c;
    void* extraArg;
}

void main() {
    auto c = new C();
    c.s = "the class member";

    // Assuming some extra argument
    int mainArg = 42;

    // Combine with the class object; this may have to be on the heap
    auto args = MyThreadArgs(c, &mainArg);

    // Do what the library wants
    libraryCreateThread(&myNonMemberThreadFunc, cast(void*)&args);
}

> Error: function `_server.Server.ClientThread(void* param)` is not
> callable using argument types `()`. too few arguments, expected `1`, got
> `0`

That looks like the same problem you had a couple of days ago: The name of the function is not a function pointer in D but is a call to it:

- foo: The same thing as foo()
- &foo: 'function'

Ali

September 11, 2022
On 9/11/22 09:26, Ali Çehreli wrote:

> // This combines a class instance (which is a pointer behind the scene)

>      // Combine with the class object

In both places I meant "class variable".

Ali
September 11, 2022
On Sunday, 11 September 2022 at 16:26:10 UTC, Ali Çehreli wrote:
> On 9/11/22 02:54, Injeckt wrote:
>
> > [...]
>
> You can combine your class object with other arguments and your thread function will know how to unwrap your class object to call its member function:
>
> [...]

Thank you for help, comrade. I just passed class object as a parameter and now I got "context".