[英]Problems with C callback function with C++ non-static member function
I have a C library that requires a callback function. 我有一个C库,需要回调函数。
void func( int *a, double *b, double *c, double *d )
a, b, c are input while 'd' is output. 输入a,b,c,输出“ d”。 My class looks like:
我的课看起来像:
class Test{
public:
Test()
{
a = 2;
ip = new int[128];
kd = new int[a];
c = new double[a];
dp = new double[26];
ja = NULL;
h = 1.0e-7;
hm = 1.0e-14;
ep = 1.0e-8;
tr = 1.0e-3;
for (int i = 0; i < 128; ++i)
ip[i] = 0;
b = 0.0;
t_e = 160.e0;
c[0] = 2.e0;
c[1] = 0.e0;
}
void my_func( int *a, double *b, double *c, double *d ) {
d[0] = some_value;
d[1] = some_other_value;
}
operator()()
{
auto member_func = std::bind( &Test::my_func, *this, _1, _2, _3, _4 );
external_function( ip, &a, &b, &t_e, c, &member_func, ja, &h, &hm, &ep, &tr, dp, kd, &ie );
}
private:
int *ip, *kd;
int a, ie;
double b, t_e;
double *c, *dp;
double h, hm, ep, tr;
void *ja;
};
It compiles fine but when run, it gives "Segmentation fault (core dumped)". 它可以正常编译,但运行时会显示“分段错误(内核已转储)”。 I don't know why this occurs.
我不知道为什么会这样。
Without using the member function (my_func), ie, if I declare, define and use "func" directly in the global scope, it works fine and produces the correct result. 如果不使用成员函数(my_func),即直接在全局范围内声明,定义和使用“ func”,则该函数可以正常工作并产生正确的结果。
The problem is then I can't have several instances of the Test class running simultaneously in parallel as they each need to modify and use class data members. 问题是,我不能同时并行运行Test类的多个实例,因为它们每个都需要修改和使用类数据成员。 Unfortunately, "func" takes no argument, eg, (void * data) that allows a cast to a 'Test'.
不幸的是,“ func”不带任何参数,例如(void * data)允许强制转换为“ Test”。
Could I have some help. 我可以帮忙吗? Many thanks.
非常感谢。
Because my_func is a memberfunction, it has a different calling convention to C function, which accomodates a hidden this pointer. 因为my_func是成员函数,所以它与C函数具有不同的调用约定,该约定容纳一个隐藏的this指针。 if you want to include a callback for C in a class, declare it
static extern "C"
. 如果要在类中包含C的回调,则将其声明为
static extern "C"
。
Are you sure the proper prototype for external_function(...)
is visible in you compilation unit? 您确定在您的编译单元中可见
external_function(...)
的正确原型吗?
Some examples: 一些例子:
extern "C" int f1(char(*)(void*,int,int), void* ctx);
extern "C" int f2(char(*)(int,int));
static callbacks* global; // Maybe thread local for thread safety...
extern "C" char cb1_helper(void* ctx, int a, int b) {
return ((callbacks*)ctx)->cb(a, b);
}
extern "C" char cb2_helper(int a, int b) {
return global->cb(a, b);
}
class callbacks {
char cb(int, int) {}
}
int main() {
callbacks A();
f1(cb1_helper, &A);
global = &A;
f2(cb2_helper);
return 0;
}
std::bind will not help you because you need a context to call a class method. std :: bind不会为您提供帮助,因为您需要上下文来调用类方法。 If callback gets some context from its arguments you can use a free function or static method as a callback:
如果callback从其参数中获取了一些上下文,则可以使用自由函数或静态方法作为回调:
typedef void (*Callback)(void* context, int arg1);
class A {
public:
void method(int arg1);
private:
static void callback(void* context, int arg1)
{
A* a = getObjectFromContext(context);
if (a)
a->method(arg1);
}
// getObjectFromContext may be implemented different ways
// simpliest case, just cast to A*
static A* getObjectFromContext(void* context)
{
return reinterpret_cast<A*>(context);
}
};
This works with a single thread and with multiple threads: 这适用于单线程和多线程:
// C function
void func( int *a, double *b, double *c, double *d );
// Forward declaration of Test class
class Test;
// Thread local for thread safety
thread_local Test *p_global;
class Test{
public:
Test()
{
a = 2;
ip = new int[128];
kd = new int[a];
c = new double[a];
dp = new double[26];
ja = NULL;
h = 1.0e-7;
hm = 1.0e-14;
ep = 1.0e-8;
tr = 1.0e-3;
for (int i = 0; i < 128; ++i)
ip[i] = 0;
b = 0.0;
t_e = 160.e0;
c[0] = 2.e0;
c[1] = 0.e0;
}
void assign_this_pointer_to_global_and_dostuff()
{
p_global = this;
dostuff();
}
dostuff()
{
external_function( ip, &a, &b, &t_e, c, &func, ja, &h, &hm, &ep, &tr, dp, kd, &ie );
}
private:
int *ip, *kd;
int a, ie;
double b, t_e;
double *c, *dp;
double h, hm, ep, tr;
void *ja;
};
// C function
void func( int *a, double *b, double *c, double *d ) {
d[0] = some_value;
d[1] = some_other_value;
}
int main()
{
Test test;
std::thread t1( &Test::assign_this_pointer_to_global_and_dostuff, &test );
//Join the thread with the main thread
t1.join();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.