简体   繁体   中英

A pointer to member is not valid for a managed class

I created a library in which one exposed function accepts a function pointer of type void(*fun_ptr)(int) .

The function syntax is:

start_server(char *devices, char *folder, int number, int timeout, void(*status_of_server)(int));

This is working with normal C++ functions like void getStatus(int n); but when I used them in a Visual C++ environment for a GUI application, I'm getting this error:

A pointer to member is not valid for a managed class

start_server(&devs, &base, 1, 0, &TestApplication::MainWindow::StatusOfServer );

Where StatusOfServer is defined inside the MainWindow class which can be used for UI management.

private: void TestApplication::MainWindow::StatusOfServer(int n)
{
    this->progressBar->Value = n;
}

What is the correct way of handling this?

The reason for the weird behavior is that each member function has implicitly appended to it's signature a pointer to it's type, eg :

#include  <iostream>

struct S
{
    int i;
    void doSth() { std::cout << i << std::endl; }
};

int main()
{
    S s{1};
    s.doSth();
    auto member_f = &S::doSth;
    (s.*member_f)();
}

doSth() has a hidden parameter, so it can't be called like a regular function. In your example the situation is similar- you are trying to call member function as if it was a normal free function, which will not work. Usually in APIs requesting function pointers, the functions can take void* as parameter, which allows you to write a wrapper that will cast the pointer to the correct type and then invoke member function on the pointed to instance of the class. However from the code you've shown above, you can't pass void* into the function, so you'll have probably have some sort of global state (eg make that function static and let it work only on static data).

One solution would be to create a small non-managed wrapper function around the managed one:

void wrapStatusOfServer(int n) {
    TestApplication::MainWindow::StatusOfServer(n)
}

and get a pointer to the wrapper

start_server(&devs, &base, 1, 0, &wrapStatusOfServer);

Another solution: turn your start_server into managed code and use a delegate instead of a function pointer: https://docs.microsoft.com/en-us/cpp/dotnet/how-to-define-and-use-delegates-cpp-cli?view=vs-2017

C++/CLI is fraught with this kind of issue, where managed and un-managed code and data are almost but not quite interoperable.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM