c/c++语言开发共享如何将C ++回调传递给C库函数?

我正在使用C ++开发我的代码,并希望使用MPFIT非线性曲线拟合库,它是用C开发的,但允许用C ++编译。

例如,我有一个名为“myClass”的类,这个类有一个函数myClass :: Execute()

我在myClass.h文件中包含“mpfit.h”。 并尝试从Execute()调用一个名为mpfit的函数。

int status = mpfit(ErrorFunction, num1, num2, xsub_1D, 0, 0, (void *) &variables, &result); 

问题是ErrorFunction是myClass的一个function。 所以编译器在我尝试使用它时会出错。 我试图从类对象中携带Erro​​rFunction,但这次我采取下面给出的错误:

ErrorFunction在类之外时出错:

错误4错误C2664:’mpfit’:无法将参数1从’int(__ cdecl *)(int,int,double *,double,double *,void *)’转换为’mp_func’

ErrorFunction在类中时出错:

 Error 3 error C3867: 'myClass::ErrorFunction': function call missing argument list; use '&myClass::ErrorFunction' to 

错误函数的定义:

 int ErrorFunction(int dummy1, int dummy2, double* xsub, double *diff, double **dvec, void *vars) 

如何调用此函数并将其解析为mpfit,这是一个C函数?

mp_func定义为:

 /* Enforce type of fitting function */ typedef int (*mp_func)(int m, /* Number of functions (elts of fvec) */ int n, /* Number of variables (elts of x) */ double *x, /* I - Parameters */ double *fvec, /* O - function values */ double **dvec, /* O - function derivatives (optional)*/ void *private_data); /* I/O - function private data*/ 

    确保您的呼叫约定匹配。 C库使用C调用约定或cdecl(__ cdecl)。 如果你在C ++中使用mp_func typedef,它可能默认为编译器的标准调用约定或stdcall(__stdcall)。 创建一个新的typedef或将其更改为以下内容:

     typedef int __cdecl (*mp_func)(int m, /* Number of functions (elts of fvec) */ int n, /* Number of variables (elts of x) */ double *x, /* I - Parameters */ double *fvec, /* O - function values */ double **dvec, /* O - function derivatives (optional)*/ void *private_data); /* I/O - function private data*/ 

    当您声明ErrorFunction时,也将其声明为__cdecl:

     int __cdecl ErrorFunction(int, int, double*, double *, double **, void *); 

    如果编译器在调用mpfit函数时仍然抱怨,您可以尝试使用cdecl将函数指针转换为mp_func typedef:

     int status = mpfit((mp_func)ErrorFunction, num1, num2, xsub_1D, 0, 0, (void *) &variables, &result); 

    鉴于您已经显示的mpfit()mp_func的定义,您需要使用mp_funcprivate_data参数来传递您的类的this指针。 您当前正在使用该参数来传递variables项。 使variables成为您的类的成员(如果它还没有),然后将其传递给mpfit()

     class MyClass { private: TheDataType variables; static int ErrorFunction(int m, int n, double *x, double *fvec, double **dvec, MyClass *pThis); public: void DoIt(); }; void MyClass::DoIt() { // ... int status = mpfit((mp_func)&ErrorFunction, num1, num2, xsub_1D, 0, 0, this, &result); // ... } int MyClass::ErrorFunction(int m, int n, double* x, double *fvec, double **dvec, MyClass *pThis) { // use pThis->variables as needed ... } 

    要么:

     class MyClass { private: static int MPFitErrorFunction(int m, int n, double *x, double *fvec, double **dvec, MyClass *pThis); int MyErrorFunction(int m, int n, double *x, double *fvec, double **dvec); public: void DoIt(); }; void MyClass::DoIt() { // ... int status = mpfit((mp_func)&MPFitErrorFunction, num1, num2, xsub_1D, 0, 0, this, &result); // ... } int MyClass::MPFitErrorFunction(int m, int n, double* x, double *fvec, double **dvec, MyClass *pThis) { return pThis->MyErrorFunction(m, n, x, fvec, dvec); } int MyClass::MyErrorFunction(int m, int n, double* x, double *fvec, double **dvec) { // use this->variables as needed ... } 

    看起来而不是:

     int ErrorFunction(int dummy1, int dummy2, double* xsub, double diff, double *dvec, void *vars) 

    它应该是:

     int ErrorFunction(int dummy1, int dummy2, double* xsub, double *diff, double **dvec, void *vars) 

    匹配你的

     typedef int (*mp_func)(int m, /* Number of functions (elts of fvec) */ int n, /* Number of variables (elts of x) */ double *x, /* I - Parameters */ double *fvec, /* O - function values */ double **dvec, /* O - function derivatives (optional)*/ void *private_data); /* I/O - function private data*/ 

    您的回调必须声明为extern "C"才能生效。

    编辑 :我看到人们很难掌握这个事实。 标准说(7.5 / 1):

    具有不同语言链接的两种函数类型是不同的类型,即使它们在其他方面相同。

    使用pimpl习惯用法有一个标准的C ++ – to – C习语:

    foo_c.h:

     #ifdef __cplusplus extern "C" { #endif //forward declaration. clients of foo_c.h should only hold pointers to Foo_c typedef struct Foo_c Foo_c; int someMethod(Foo_c* foo); #ifdef __cplusplus } #endif 

    foo_c.cpp:

     #include  struct Foo_c { Foo foo; } int someMethod(Foo_c* foo) { try { foo->foo.someMethod(); return 0; //no error } catch(...) { return 1; //error } } 

    (根据以下答案编辑为外部“C”。)

      以上就是c/c++开发分享如何将C ++回调传递给C库函数?相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注计算机技术网(www.ctvol.com)!)。

      本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。

      ctvol管理联系方式QQ:251552304

      本文章地址:https://www.ctvol.com/c-cdevelopment/549943.html

      (0)
      上一篇 2021年1月14日
      下一篇 2021年1月14日

      精彩推荐