是该C回调的安全与C ++对象? [英] Is this C callback safe with C++ objects?

查看:147
本文介绍了是该C回调的安全与C ++对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的目的是呼吁从我的C ++ code一些C函数和通过一些C ++对象。
其实我使用从GSL libray(用C编写的)一个整合常规,看到这个<一个href=\"http://scicomp.stackexchange.com/questions/4730/numerical-integration-handling-nans-c-fortran\">link,

My purpose is to call some C function from my C++ code and pass some C++ objects. In fact I am using a integration routine from the GSL libray(written in C), see this link,

我的code片断:

// main.cpp

#include <stdio.h>
#include <gsl/gsl_integration.h>
#include <myclass.h>

/* my test function. */
double testfunction ( double x , void *param ) {
    myclass *bar=static_cast<myclass*>(param);

    /*** do something with x and bar***/ 

    return val;

    }

int main ( int argc , char *argv[] ) {

    gsl_function F;  // defined in GSL: double (* function) (double x, void * params)

    /* initialize.*/
    gsl_integration_cquad_workspace *ws = 
    gsl_integration_cquad_workspace_alloc( 200 ) ;    

    /* Prepare test function. */
    myclass foo{}; // call myclass constructor
    F.function = &testfunction;
    F.params =   &foo;


    /* Call the routine. */
    gsl_integration_cquad( &F, 0.0,1.0,1.0e-10,1.0e-10,ws, &res,&abserr,&neval); 


    /* Free the workspace. */
    gsl_integration_cquad_workspace_free( ws );

    return 0;

    }

在我的情况下,直接调用gsl_integration_cquad看起来不错,提供的标题包括某事象的ifdef __cplusplus,我关心的是关于在回调˚F,原本在C中定义,我是不是允许通过的testfunction也是C ++的这样的对象?

In my case, direct calling gsl_integration_cquad seems OK, provided the header includes sth like "ifdef __cplusplus", my concern is about the callback F,originally defined in C, am I allowed to pass the testfunction and also the C++ foo object in this way ? .

或者是还有什么更好的办法做这样的东西,也许超载和使用仿函数?

or is there any better way to do this kind of stuff, maybe overloading and use a functor?

P.S。我是否允许做exeption在回调函数中处理? (使用尝试捕捉里面的testfunction)。它工作在我的情况,但不知道这是否是合法的。

P.S. Am I allowed to do exeption handling within the callback function? (use try catch inside "testfunction"). It works in my case but not sure if it's legal.

推荐答案

我不熟悉的问题库,但总的来说,
指针传递到回调和无效*当
一个C程序,该程序会调用回调回来的无效*
有两件事情你需要做的,使之安全:

I'm not familiar with the library in question, but in general, when passing a pointer to a callback and a void* to a C routine, which will call the callback back with the void*, there are two things you need to do to make it safe:


  • 函数的地址传递必须声明的的externC的。
    你会逃脱不有很多编译器这样做,但
    这是不合法的,而且一个好的编译器会抱怨。

  • The function whose address you pass must be declared extern "C". You'll get away with not doing this with a lot of compilers, but it isn't legal, and a good compiler will complain.

类型,你转换为无效* 必须是完全一样的
键入你施放回回调的类型。该
经典的错误是通过类似新派生来的
C函数,并在回调将它转换回基础* 。该
往返派生* &RARR; 无效* &RARR; 基础* 是未定义
行为。它将工作了一些时间,但在其他时候,它
可能会崩溃,或者引起很多其他问题。

The type you convert to the void* must be exactly the same type as the type you cast it back to in the callback. The classic error is to pass something like new Derived to the C function, and cast it back to Base* in the callback. The round trip Derived*void*Base* is undefined behavior. It will work some of the time, but at other times, it may crash, or cause any number of other problems.

和作为cdhowie在评论中指出的那样,你不想要
允许例外的防空火炮C $ C $Ç传播。再次,这
可能工作。但它可能并非如此。

And as cdhowie pointed out in a comment, you don't want to allow exceptions to propagate accross the C code. Again, it might work. But it might not.

有关您发布确切的例子,你需要做的唯一的事情
正在申报 testfunction 的externC,和你所有的
对。如果以后开始使用多态对象的工作,
然而,提防第二点的。

For the exact example you posted, the only thing you need to do is to declare testfunction as extern "C", and you're all right. If you later start working with polymorphic objects, however, beware of the second point.

这篇关于是该C回调的安全与C ++对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆