Указатель на член недопустим для управляемого класса - PullRequest
0 голосов
/ 07 сентября 2018

Я создал библиотеку, в которой одна открытая функция принимает указатель на функцию типа void (* fun_ptr) (int).

Синтаксис функции:

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

Это работает с обычными функциями C ++, такими как void getStatus (int n); Но когда я использовал их в визуальной среде C ++ для приложения с графическим интерфейсом, я получаю эту ошибку: Недопустимый указатель на член для управляемого класса

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

где StatusOfServer определен внутри класса MainWindow, который может использоваться для управления пользовательским интерфейсом.

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

Как правильно обращаться с этим.

Ответы [ 2 ]

0 голосов
/ 07 сентября 2018

Одним из решений было бы создание небольшой неуправляемой функции-оболочки вокруг управляемой:

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

и получите указатель на оболочку

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

Другое решение: превратите ваш start_server в управляемый код и используйте делегат вместо указателя функции: https://docs.microsoft.com/en-us/cpp/dotnet/how-to-define-and-use-delegates-cpp-cli?view=vs-2017

C ++ / CLI связан с проблемами такого рода, когда управляемый и неуправляемый код и данные практически, но не совсем совместимы.

0 голосов
/ 07 сентября 2018

Причина странного поведения заключается в том, что каждая функция-член неявно добавляет к своей подписи указатель на свой тип, например, :

#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() имеет скрытый параметр, поэтому его нельзя вызывать как обычную функцию. В вашем примере ситуация аналогична - вы пытаетесь вызвать функцию-член, как если бы это была обычная свободная функция, которая не будет работать. Обычно в API, запрашивающих указатели на функции, функции могут принимать void* в качестве параметра, который позволяет написать оболочку, которая приведёт указатель к правильному типу, а затем вызовет функцию-член в указанном экземпляре класса. Однако из кода, который вы показали выше, вы не можете передать void* в функцию, поэтому у вас, вероятно, будет какое-то глобальное состояние (например, сделайте эту функцию статической и разрешите ей работать только со статическими данными).

...