我创建了一个库,其中一个公开的函数接受void(* fun_ptr)(int)类型的函数指针。
函数语法是:
start_server(char *devices, char *folder, int number, int timeout, void(*status_of_server)(int));
这适用于正常的C ++函数,如void getStatus(int n);但是当我在GUI应用程序的可视化C ++环境中使用它们时,我收到了这个错误:指向成员的指针对托管类无效
start_server(&devs, &base, 1, 0, &TestApplication::MainWindow::StatusOfServer );
StatusOfServer在MainWindow类中定义,可用于UI管理。
private: void TestApplication::MainWindow::StatusOfServer(int n)
{
this->progressBar->Value = n;
}
处理这个问题的正确方法是什么。
一种解决方案是围绕托管的函数创建一个小的非托管包装函数:
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充满了这类问题,托管和非托管代码和数据几乎可以互操作。
奇怪行为的原因是每个成员函数都隐式地在其签名上附加了指向它的类型的指针,例如, :
#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*
传递给函数,因此您可能会有某种全局状态(例如,将该函数设置为静态并使其仅适用于静态数据)。