从库B中的库A更改函数指针

时间:2011-07-26 16:30:01

标签: c++ matlab function-pointers libraries

我的情况如下:

我正在编写一个生成两个库的工具箱。第一个(A)具有所有函数和数据类型,可以在纯C ++应用程序中使用;第二个(B)是MATLAB的接口。 一个纯C ++程序将用

编译
g++ $(FLAGS) C.cpp $(MOREFLAGS) -lA

而MATLAB程序将在A之后用B链接编译,即

mex $(FLAGS) C.cpp $(MOREFLAGS) -lA -lB

现在,我想使用函数指针(myexit)为纯C ++应用程序调用{​​{1}},为MATLAB应用程序调用{​​{1}}(调用std::exit())。在关于函数指针的教程之后,我写了类似下面的片段(一切都在命名空间内,但为了简洁起见我已经将其抑制了)。

mex_exit()

我上面的内容似乎适用于纯C ++代码,我发现如果我在C.cpp中包含行mexErrMsgTxt(),我可以获得MATLAB代码的正确行为,但是,我希望这个行为只是来自在C.cpp中有//A.hpp #ifndef __A #define __A extern void (*myexit)(int); ... #ifdef mex_h /* defined in mex.h */ #include "B.hpp" #endif /* mex_h */ #endif /* __A */ //A.cpp #include "A.hpp" void (*myexit)(int) = &std::exit; //B.hpp #ifndef __B #define __B #include <mex.h> #include "A.hpp" ... void mex_exit(int); #endif /* __B */ //B.cpp #include <mex.h> #include "A.hpp" void mex_exit(int err) {mexPrintf("Error code %d\n",err); mexErrMsgTxt("...");} //void (*myexit)(int) = &mex_exit; // <- I want a line like this to override the line in A.cpp myexit = &mex_exit;并链接到B(即用户不应该包含此行)。

这可能吗?如果是这样,那怎么样?

3 个答案:

答案 0 :(得分:3)

在库B中,添加一个静态构造函数来设置myexit

// Consider putting this into a namespace
extern void (*myexit)(int);

// anonymous namespace to avoid name collisions
namespace {
class StaticInit {
  StaticInit() {
    myexit = mex_exit;
  }
} static_init_obj;
}

然后链接库B以依赖库A:

gcc -o libB.so -shared -lA -lmatlab b.o

因为libB依赖于libA,所以在libB静态构造函数之前将调用libA静态构造函数,因此排序不是问题。 StaticInit构造函数将在程序启动期间(main()之前)调用,并为您设置myexit

答案 1 :(得分:1)

您可以将GCC constructor function attribute应用于B.cpp中的函数,该函数会覆盖myexit的值。

当然不便携。

答案 2 :(得分:0)

我不确定你可以做什么(可移植,就是这样)。也许您可以做的最好的事情是在B中提供init函数,为“Matlab模式”设置所有内容,包括更改myexit函数指针。这样,用户就不知道实现细节。这种方法的优点是,如果以后需要添加更多初始化代码,可以将其添加到init函数中,而不会破坏客户端的代码。

我认为将函数指针作为库API的一部分是个坏主意。您应该提供一个myexit函数,代表用户调用函数指针:

void myexit(int err) {myexit_fn_ptr(err);}

当您使用它时,请提供清理功能作为库API的一部分。此函数与init的对应函数必须在程序退出之前由客户端调用,以便库可以执行清理。即使您目前没有要进行清理工作,也要在API中添加一个空的清理功能,以便您拥有未来的占位符。