天道酬勤,学无止境

将成员函数指针传递给C样式函数(Passing member function pointer to the c-style function)

问题

我正在尝试将成员函数指针传递给c样式函数(因为它在C语言中是lib)

它想要的指针定义为:

void (*)(int, const char*)

所以我想传递的函数是:

void Application::onError(int error, const char *description)

我正在尝试通过以下代码传递它:

setCallback(bind(&Game::onError, this, placeholders::_1, placeholders::_2));

这给了我以下错误:

cannot convert ‘std::_Bind_helper<false, void (Application::*)(Application*, int,
const char*), Application* const, const std::_Placeholder<1>&, const 
std::_Placeholder<2>&>::type {aka std::_Bind<std::_Mem_fn<void (Application::*)
(Application*, int, const char*)>(Application*, std::_Placeholder<1>,
std::_Placeholder<2>)>}’ to ‘GLFWerrorfun {aka void (*)(int, const char*)}’ for 
argument ‘1’ to ‘void (* glfwSetErrorCallback(GLFWerrorfun))(int, const char*)’
glfwSetErrorCallback(bind(&Application::onError, this, placeholders::_1, placeholders::_2));

有什么方法可以成功地将成员函数作为绑定函数传递给c样式函数?

回答1

std::bind的结果是一个复杂的C ++对象。 例如,它必须存储所有绑定的参数。 因此,它绝对不能转换为函数指针。

您正在处理的回调规范显然不允许“用户数据”有效负载,因此没有地方可以隐藏指向可用于调用非静态成员函数的C ++对象的指针。 这意味着您将必须调用全局或静态成员函数,或诉诸于全局/静态成员/每个线程变量来存储对象指针。

唯一100%可移植的方法是创建一个C链接函数用作回调。 这样做,并使用全局对象指针来调用原始的onError()

Application *error_handling_application;

extern "C" void errorCallback(int error, const char *description)
{
  error_handling_application->onError(error, description);
}

请注意,经常会遇到使用静态成员函数代替我的errorCallback 。 这适用于大多数平台上的大多数编译器,但不能保证能正常工作。 C库期望具有C语言链接的功能。 静态成员函数只能具有C ++语言链接。 C函数和C ++函数的调用机制可能会有所不同(取决于ABI),这将导致对传入的静态成员函数的调用格式错误。

回答2

由于成员函数还具有this指针作为隐含参数,因此它不是C函数接受的类型。 因此,恕我直言,唯一的方法是生成具有C链接的独立函数

class A {
public: void func(int, const char*) const;
};

extern "C" {
  void cfunc(void(*)(int, const char*));
  void call_cfunc(const A*);
}

// in some source (non-header) file:
namespace {
  const A*pa;
  void afunc(int i, const char*s)
  { pa->func(i,s); }
}

void call_cfunc(const A*a)
{
  pa = a;
  cfunc(afunc);
}
回答3

不直接,不。 一个C ++成员函数需要一个隐式this指针,而C对此当然不知道并且不会通过。

解决此问题的通常方法是将“蹦床”作为类方法引入,但是在更现代的C ++变体中也许有更漂亮的方法。

受限制的 HTML

  • 允许的HTML标签:<a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。

相关推荐
  • 传递函子作为函数指针(passing functor as function pointer)
    问题 我正在尝试在C ++应用程序中使用C库,并且在以下情况下发现了自己(我知道我的C,但是我对C ++还是很陌生)。 在C端,我有一个函数集合,这些函数将函数指针作为其参数。 在C ++方面,我有带有函子的对象,该函子具有与C函数所需的函数指针相同的签名。 有什么方法可以将C ++函子用作传递给C函数的函数指针吗? 回答1 您不能直接将指向C ++函子对象的指针作为指向C代码(甚至C ++代码)的函数指针。 另外,为了可移植地将回调传递给C代码,至少需要将其声明为extern "C"非成员函数。 至少因为某些API需要特定的函数调用约定,因此还需要其他声明修饰符。 在许多环境中,C和C ++具有相同的调用约定,并且仅在名称修饰上有所不同,因此任何全局函数或静态成员都可以使用。 但是您仍然需要将对operator()的调用包装在普通函数中。 如果您的函子没有状态(它只是满足某些正式要求等的对象): class MyFunctor { // no state public: MyFunctor(); int operator()(SomeType &param) const; } 您可以编写一个普通的extern“ C”函数,该函数创建函子并执行其operator()。 extern "C" int MyFunctorInC(SomeType *param) { static
  • 在C ++中将成员函数指针传递给成员对象(Passing member function pointer to member object in c++)
    问题 我在使用指针在C ++中运行时遇到问题。 这是我的示例: #include <iostream> using namespace std; class bar { public: void (*funcP)(); }; class foo { public: bar myBar; void hello(){cout << "hello" << endl;}; }; void byebye() { cout << "bye" << endl; } int main() { foo testFoo; testFoo.myBar.funcP = &byebye; //OK testFoo.myBar.funcP = &testFoo.hello; //ERROR return 0; } 编译器在testFoo.myBar.funcP = &testFoo.hello;处返回错误testFoo.myBar.funcP = &testFoo.hello; : ISO C ++禁止使用绑定的成员函数的地址来形成指向成员函数的指针。 说'&foo :: hello' 无法将赋值中的'void(foo :: )()'转换为'void( )()' 所以我这样尝试了: class bar { public: void (*foo::funcP)(); }; 但是现在,编译器又添加了一个:
  • 将指针传递给类成员函数作为参数(Passing a pointer to a class member function as a parameter)
    问题 我编写了一个小程序,试图将指向类成员函数的指针传递给另一个函数。 您能帮我吗,我哪里出了问题..? #include<iostream> using namespace std; class test{ public: typedef void (*callback_func_ptr)(); callback_func_ptr cb_func; void get_pc(); void set_cb_ptr(void * ptr); void call_cb_func(); }; void test::get_pc(){ cout << "PC" << endl; } void test::set_cb_ptr( void *ptr){ cb_func = (test::callback_func_ptr)ptr; } void test::call_cb_func(){ cb_func(); } int main(){ test t1; t1.set_cb_ptr((void *)(&t1.get_pc)); return 0; } 尝试编译时出现以下错误。 error C2276: '&' : illegal operation on bound member function expression 回答1 您不能将函数指针强制转换为void* 。
  • C语言中的三重指针:这是样式问题吗?(Triple pointers in C: is it a matter of style?)
    问题 我觉得C中的三重指针被视为“错误”。 对我来说,有时使用它们是有意义的。 从基础开始,单个指针具有两个目的:创建数组,并允许函数更改其内容(通过引用传递): char *a; a = malloc... 或者 void foo (char *c); //means I'm going to modify the parameter in foo. { *c = 'f'; } char a; foo(&a); 双指针可以是2D数组(或数组的数组,因为每个“列”或“行”的长度不必相同)。 我个人喜欢在需要传递一维数组时使用它: void foo (char **c); //means I'm going to modify the elements of an array in foo. { (*c)[0] = 'f'; } char *a; a = malloc... foo(&a); 对我来说,这有助于描述foo在做什么。 但是,没有必要: void foo (char *c); //am I modifying a char or just passing a char array? { c[0] = 'f'; } char *a; a = malloc... foo(a); 也可以。 根据对这个问题的第一个答案,如果foo要修改数组的大小,则将需要一个双指针。
  • 将struct传递给函数(Passing struct to function)
    问题 我是一名新的C程序员,我想知道如何将struct传递给函数。 我遇到错误,无法找出正确的语法来做到这一点。 这是它的代码。 结构: struct student{ char firstname[30]; char surname[30]; }; struct student person; 称呼: addStudent(person); 原型: void addStudent(struct student); 和实际功能: void addStudent(person) { return; } 编译器错误: 第21行:警告:可疑标签声明:结构体学生第223行:参数#1与原型不兼容: 回答1 线路功能的实现应为: void addStudent(struct student person) { } person不是类型而是变量,您不能将其用作函数参数的类型。 另外,请确保在函数addStudent的原型之前定义了您的结构,因为原型已使用它。 回答2 这是通过引用传递struct的方法。 这意味着您的函数可以访问struct外部的struct并修改其值。 您可以通过将指向结构的指针传递给函数来完成此操作。 #include <stdio.h> /* card structure definition */ struct card { int face; // define
  • 如何传递成员函数指针?(How do you pass a member function pointer?)
    问题 我试图将类中的成员函数传递给采用成员函数类指针的函数。 我遇到的问题是我不确定如何使用this指针在类中正确执行此操作。 有人有建议吗? 这是传递成员函数的类的副本: class testMenu : public MenuScreen{ public: bool draw; MenuButton<testMenu> x; testMenu():MenuScreen("testMenu"){ x.SetButton(100,100,TEXT("buttonNormal.png"),TEXT("buttonHover.png"),TEXT("buttonPressed.png"),100,40,&this->test2); draw = false; } void test2(){ draw = true; } }; 函数x.SetButton(...)包含在另一个类中,其中“对象”是模板。 void SetButton(int xPos, int yPos, LPCWSTR normalFilePath, LPCWSTR hoverFilePath, LPCWSTR pressedFilePath, int Width, int Height, void (object::*ButtonFunc)()) { BUTTON::SetButton(xPos, yPos
  • 使用引用作为类成员的依赖关系(Using reference as class members for dependencies)
    问题 我花了一些时间在内存管理的语言上后回到C ++,突然之间我迷失了什么是实现依赖注入的最佳方法。 (我被完全卖给了DI,因为我发现它是使测试驱动的设计变得非常容易的最简单方法)。 现在,浏览SO和google在这件事上给了我很多意见,我有点困惑。 为了回答这个问题,C ++中的依赖注入,有人建议您不要传递原始指针,即使是依赖注入也是如此。 我了解这与对象的所有权有关。 现在,在臭名昭着的谷歌风格指南中,对象的所有权也得到了解决(尽管没有足够详细的信息;)):http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Smart_Pointers 因此,我的理解是,为了更清楚地知道哪个对象对其他对象拥有所有权,应该避免传递原始指针。 特别是,这似乎与这种编码背道而驰: class Addict { // Something I depend on (hence, the Addict name. sorry.) Dependency * dependency_; public: Addict(Dependency * dependency) : dependency_(dependency) { } ~Addict() { // Do NOT release dependency_, since it was
  • 将C ++函数指针转换为C函数指针(Convert C++ function pointer to c function pointer)
    问题 我正在使用C库开发C ++应用程序。 我必须发送一个指向函数的指针到C库。 这是我的课: class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = 0); private: Ui::MainWindow *ui; void f(int*); private slots: void on_btn_clicked(); }; 这是我的on_btn_clicked函数: void MainWindow::on_btn_clicked() { void (MainWindow::* ptfptr) (int*) = &MainWindow::f; c_library_function(static_cast<void()(int*)>(ptfptr), NULL); } C函数应该获得指向此类函数的指针:void f(int *)。 但是上面的代码不起作用,我无法成功将f成员函数转换为所需的指针。 有人可以帮忙吗? 回答1 如果我没记错的话,则只能通过指向函数语法的“普通” C指针访问类的静态方法。 因此,请尝试使其变为静态。 指向类的方法的指针需要额外的信息,例如“对象”(this),对于纯C方法没有任何意义。 此处显示的FAQ很好地解释了您的问题
  • C指针表示法与数组表示法的比较:传递给函数时(C pointer notation compared to array notation: When passing to function)
    问题 我的问题基于以下代码: int myfunct(int ary[], int arysize) int myfunct2(int *ary, int arysize) int main(void){ int numary[10]; myfunct(numary, 10) myfunct2(numary, 10) return; } int myfunct(int ary[], int arysize) { //Whatever work is done } int myfunct2(int *ary, int arysize) { // Whatever work is done } 是否有理由在其中之一上使用其中之一? 详细地说,当涉及数字数组时,有什么理由要使用指针表示法而不是数组表示法。 如果使用指针表示法,则在函数内将使用指针算术等。并且如果使用[]数组表示法,则可以照常使用该数组。 我是编程的新手,我目前看不到使用指针表示法的任何好处。 我的确切问题是,是否有任何理由使用指针表示法将数字数组传递给函数,并因此在函数内使用指针操纵。 回答1 两种表示法之间没有真正的功能差异。 在C语言中,当您将数组变量传递给函数时,无论使用哪种符号,它都会衰减为指针。 但是,在我看来,指针符号是可取的。 我认为函数定义中[]表示法的问题在于,它在某种程度上具有误导性: void
  • C API函数回调到C ++成员函数代码中(C API function callbacks into C++ member function code)
    问题 因此,我正在使用FMOD api,它确实是C api。 并不是说那很坏或什么。 它只是不能很好地与C ++代码接口。 例如,使用 FMOD_Channel_SetCallback( channel, callbackFunc ) ; 它需要一个C样式的callbackFunc函数,但我想将其传递给类的成员函数。 我最终使用Win32技巧,使成员函数成为静态。 然后,它用作FMOD的回调。 现在,我不得不分拆我的代码,以使某些成员成为静态成员,以解决FMOD的C-ness问题。 我想知道它是否可以在FMOD中使用,还是可以解决将回调链接到特定C ++对象的实例成员函数(而不是静态函数)的问题。 这样会更顺畅。 回答1 您不能直接传递成员函数。 成员函数的隐含参数this和C函数没有。 您将需要创建一个蹦床(不确定回调的签名,因此请在此处随机进行)。 extern "C" int fmod_callback( ... args ...) { return object->member(); } 一个问题是该对象指针从何而来。 希望fmod为您提供一个通用的上下文值,该值将在进行回调时提供给您(然后可以传入对象指针)。 如果没有,您只需要使其成为全局变量即可访问它。 回答2 我猜它应该像这样工作: 您可以通过调用FMOD_Channel
  • 什么是C ++委托?(What is a C++ delegate?)
    问题 C ++中委托的一般思想是什么? 它们是什么?它们的用途是什么?它们的用途是什么? 我想首先以“黑匣子”的方式来了解它们,但是对这些东西的勇气有一点了解也是非常有用的。 这并不是最纯净或最纯净的C ++,但我注意到我工作的代码库中有大量的C ++。 我希望对它们有足够的了解,因此我可以只使用它们,而不必深入研究可怕的嵌套模板的糟糕性。 这两篇代码项目文章解释了我的意思,但并没有特别简洁: 成员函数指针和最快的C ++委托不可能的快速C ++代表 回答1 您可以通过多种选择来实现C ++中的委托。 这是我想到的那些。 选项1:函子: 函数对象可以通过实现operator()来创建 struct Functor { // Normal class/struct members int operator()(double d) // Arbitrary return types and parameter list { return (int) d + 1; } }; // Use: Functor f; int i = f(3.14); 选项2:lambda表达式(仅C ++ 11) // Syntax is roughly: [capture](parameter list) -> return type {block} // Some shortcuts exist auto
  • 在void *和成员函数的指针之间进行转换(Casting between void * and a pointer to member function)
    问题 我目前正在使用GCC 4.4,并且在void*和成员函数的指针之间感到颇为头痛。 我正在尝试编写一个易于使用的库,用于将C ++对象绑定到Lua解释器,如下所示: LuaObject<Foo> lobj = registerObject(L, "foo", fooObject); lobj.addField(L, "bar", &Foo::bar); 我已经完成了大部分工作,但以下函数除外(该函数特定于某个函数签名,直到我有机会将其归纳为止): template <class T> int call_int_function(lua_State *L) { // this next line is problematic void (T::*method)(int, int) = reinterpret_cast<void (T::*)(int, int)>(lua_touserdata(L, lua_upvalueindex(1))); T *obj = reinterpret_cast<T *>(lua_touserdata(L, 1)); (obj->*method)(lua_tointeger(L, 2), lua_tointeger(L, 3)); return 0; } 对于不熟悉Lua的人, lua_touserdata(L, lua_upvalueindex
  • 将捕获lambda作为函数指针传递(Passing capturing lambda as function pointer)
    问题 是否可以将lambda函数作为函数指针传递? 如果是这样,我肯定做错了什么,因为我遇到了编译错误。 考虑下面的例子 using DecisionFn = bool(*)(); class Decide { public: Decide(DecisionFn dec) : _dec{dec} {} private: DecisionFn _dec; }; int main() { int x = 5; Decide greaterThanThree{ [x](){ return x > 3; } }; return 0; } 当我尝试对此进行编译时,出现以下编译错误: In function 'int main()': 17:31: error: the value of 'x' is not usable in a constant expression 16:9: note: 'int x' is not const 17:53: error: no matching function for call to 'Decide::Decide(<brace-enclosed initializer list>)' 17:53: note: candidates are: 9:5: note: Decide::Decide(DecisionFn) 9:5: note: no
  • 指向类数据成员“ :: *”的指针(Pointer to class data member “::*”)
    问题 我碰到了这个奇怪的代码片段,可以很好地编译: class Car { public: int speed; }; int main() { int Car::*pSpeed = &Car::speed; return 0; } 为什么C ++具有指向类的非静态数据成员的指针? 什么是使用真正的代码,这个奇怪的指针? 回答1 它是“成员的指针”-以下代码说明了其用法: #include <iostream> using namespace std; class Car { public: int speed; }; int main() { int Car::*pSpeed = &Car::speed; Car c1; c1.speed = 1; // direct access cout << "speed is " << c1.speed << endl; c1.*pSpeed = 2; // access via pointer to member cout << "speed is " << c1.speed << endl; return 0; } 至于您为什么要这样做,那么它为您提供了可以解决一些棘手问题的另一种间接方式。 但是老实说,我从来没有在自己的代码中使用它们。 编辑:我不能认为有说服力的使用指向成员数据的指针。 指向成员函数的指针可用于可插拔体系结构
  • 类成员函数指针(Class member function pointer)
    问题 我正在尝试使用类函数(中断服务例程), void (ClassName::*fp)(void)=ClassName::FunctionName; 并使用具有以下类型输入的功能将其连接到Arduino中断引脚,但这是行不通的。 void attachInterrupt(int, void (*)(void),int); 我怎样才能做到这一点? 中断服务例程(ISR)需要访问私有对象数据,因此我不能在类之外创建函数。 我的编译器错误: ClassName.cpp : : In constructor 'ClassName::ClassName()': ClassName.cpp : *)()' ClassName.cpp : *)()' to 'void (*)()' for argument '2' to 'void attachInterrupt(uint8_t, void (*)(), int)' 注意:我正在课堂上寻找解决方案,并且会接受向我显示解决方案或不可能的答案。 回答1 如果该函数不是static ,则不能在输入中将其传递给接受非成员函数指针的函数。 考虑到非static成员函数具有指向ClassName的隐式指针作为其第一个参数,该指针指向在其上调用成员函数的对象。 struct X { static void foo() { } // Does not
  • 在C中用作结构成员的指针如何发挥作用?(How pointers to function as struct member useful in C?)
    问题 我对C编程并不陌生。 但是我不明白保持指针在C中作为结构成员起作用的作用是什么。例如 // Fist Way: To keep pointer to function in struct struct newtype{ int a; char c; int (*f)(struct newtype*); } var; int fun(struct newtype* v){ return v->a; } // Second way: Simple struct newtype2{ int a; char c; } var2; int fun2(struct newtype2* v){ return v->a; } int main(){ // Fist: Require two steps var.f=fun; var.f(&var); //Second : simple to call fun2(&var2); } 程序员是否使用它为C代码提供面向对象(OO)的形状并提供抽象对象? 或使代码看起来技术性。 我认为,在上述代码中,第二种方式也更加温和和简单。 用拳头的方式,我们仍然必须传递&var ,即使fun()是struct的成员。 如果将函数指针保持在struct定义之内很好,请帮助解释原因。 回答1 提供指向结构上功能的指针可使您动态选择要在结构上执行的功能。
  • 在CUDA的__global__或__device__函数中将主机函数作为函数指针传递(Passing Host Function as a function pointer in __global__ OR __device__ function in CUDA)
    问题 我目前正在开发CPU功能的GPU版本(例如,函数Calc(int a,int b,double * c,souble * d,CalcInvFunction GetInv)),其中将主机函数作为函数指针传递(例如,在上面示例GetInv是CalcInvFunction类型的宿主函数)。 我的问题是,如果我必须将Calc()函数完全放在GPU中,我必须将GetInv函数作为函数指针参数传递给设备函数/内核函数,这可能吗? 回答1 是的,对于Calc的GPU实现,您应该将GetInv作为__device__函数指针传递。 有可能,下面是一些可行的示例: 前任。 1个 前任。 2个 前任。 3 上面的大多数示例都演示了如何将设备功能指针完全带回到主机代码中。 对于您的特定情况,这可能不是必需的。 但是从上面看,如何获取__device__函数指针(在设备代码中)并在内核中使用它应该是很明显的。 回答2 最后,我已经能够将宿主函数作为函数指针传递给cuda内核函数(__global__函数)。 感谢Robert Crovella和njuffa的回答。 我已经能够将类成员函数(cpu函数)作为指向cuda内核的函数指针进行传递。 但是,主要问题是,我只能传递静态类成员函数。 我无法传递未声明为静态的函数。 例如: /**/ __host__ __device__ static int
  • C ++使用类方法作为函数指针类型(C++ Using Class Method as a Function Pointer Type)
    问题 在C库中,有一个函数在等待函数指针,例如: lasvm_kcache_t* lasvm_kcache_create(lasvm_kernel_t kernelfunc, void *closure) lasvm_kernel_t定义为: typedef double (*lasvm_kernel_t)(int i, int j, void* closure); 现在,如果我将在类中定义的方法发送给lasvm_kcache_create: double cls_lasvm::kernel(int i, int j, void *kparam) ... lasvm_kcache_t *kcache=lasvm_kcache_create(&kernel, NULL); 我得到:“无法将'double(cls_lasvm :: )(int,int,void )'转换为'double( )(int,int,void )'” 我应该怎么办? 回答1 我假设closure参数是上下文“ cookie”,用于通过回调获取适当的上下文。 这是回调函数的常见用法,它似乎是根据您提供的代码片段进行的操作(但我不确定,因为除了此处发布的内容之外,我对kcache_create()并不了解)。 您可以使用该Cookie将指针传递给您正在处理的cls_lasvm实例,如下所示: extern "C"
  • 将成员函数的指针转换为普通指针(Cast pointer to member function to normal pointer)
    问题 目前,我有一个此类,为简单起见已缩短: class MyClass { public: MyClass(); void* someFunc(void* param); } 现在,我需要调用这种函数(不是任何类的成员,但遗憾的是我无法更改该函数),但无论如何我都需要调用该函数: void secondFunc(int a, int b, void *(*pCallback)(void*)); 现在,我需要传递实例的someFunc的地址。 一个不起作用的示例: MyClass demoInstance; // some other calls secondFunc( 1, 2, demoInstance::someFunc() ); 我也尝试过像这样的演员: (void* (*)(void*)) demoInstance::someFunc; reinterpret_cast<(void* (*)(void*))>(demoInstance::someFunc); 如何使用类的成员函数作为参数来调用此函数,以便该函数可以将其用作回调? 任何想法或评论表示赞赏。 感谢和问候tobias 回答1 C函数和C ++成员函数之间的区别在于C函数使用cdecl调用约定,而成员函数使用thiscall调用约定(而且您甚至无法使用其地址!)。 据我了解,您实际上是希望secondFunc(
  • 将数组作为参数传递给C中的函数(Passing an array as an argument to a function in C)
    问题 我写了一个包含数组作为参数的函数,并通过如下传递数组的值来调用它。 void arraytest(int a[]) { // changed the array a a[0]=a[0]+a[1]; a[1]=a[0]-a[1]; a[0]=a[0]-a[1]; } void main() { int arr[]={1,2}; printf("%d \t %d",arr[0],arr[1]); arraytest(arr); printf("\n After calling fun arr contains: %d\t %d",arr[0],arr[1]); } 我发现的是,尽管我通过传递值来调用arraytest()函数,但int arr[]的原始副本已更改。 你能解释为什么吗? 回答1 当将数组作为参数传递时,这 void arraytest(int a[]) 的意思与 void arraytest(int *a) 所以您要修改main中的值。 由于历史原因,数组不是一等公民,因此不能按值传递。 回答2 1. C语言中标准数组的用法,其自然类型从数组到ptr都会衰减 @Bo Persson在此处的正确答案中正确指出: 当将数组作为参数传递时,这void arraytest(int a[]) 的意思与void arraytest(int *a) 但是,我还要补充一点