指向成员的指针对于托管类无效

时间:2018-09-07 10:06:12

标签: c++ visual-c++ function-pointers managed-c++

我创建了一个库,其中一个公开的函数接受一个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 ++环境中将它们用于GUI应用程序时,出现此错误:指向成员的指针对于托管类无效

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

其中StatusOfServer是在MainWindow类中定义的,可用于UI管理。

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

处理此问题的正确方法是什么。

2 个答案:

答案 0 :(得分:1)

一种解决方案是围绕托管对象创建一个小的非托管包装函数:

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饱受此类问题困扰,托管和非托管代码和数据几乎但并非完全可互操作。

答案 1 :(得分:0)

这种奇怪行为的原因是每个成员函数都隐式地在其签名后附加了一个指向其类型的指针,例如:

#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*传递给该函数,因此您可能会有某种全局状态(例如,使该函数成为静态状态,并使其仅对静态数据起作用) )。