从C转换为C ++后对共享库函数的未定义引用

时间:2014-07-25 17:37:59

标签: c++ c shared-libraries mex

我有一个共享库`libsharedlib.so',它曾经是从C文件生成的。由于库现在需要使用来自第三方C ++库的函数,我想将我的共享库从C转换为C ++(代码相对简单)。基于我阅读here的差异,我必须做的唯一改编就是使用stdlib和stdio函数。标题已从

更改
#include <stdio.h>
#include <stlib.h>

#include <cstdlib>
#include <cstdio>

对这些库中的函数的所有调用都以std::命名空间为前缀(例如std::malloc而不是malloc,我没有使用using namespace std)。源文件扩展名已从.c更改为.cpp。我还必须在每个文件的末尾添加换行符,并且必须强制转换malloc。之后没有其他编译器反馈。使用以下命令编译共享库:

pgcpp -shared -I./inc/ -o ./lib/libsharedlib.so file1.cpp file2.cpp ...

并且不会返回任何错误或警告。

我现在有一个MEX函数,mex_gateway.cpp调用此库中的函数:

#include "sharedlibraryheader.h"
#include "mex.h"

void mexFunction(int nlhs, mxArray *plhs[],
             int nrhs, const mxArray *prhs[]){
...
function_from_library(data);
}

使用以下命令编译

mex -L./lib/ -lsharedlib -I./inc/ mex_gateway.cpp

其中(添加详细标记-v时)实际执行以下命令:

g++ -c  -I./inc/ -I/opt/MATLAB/R2013b/extern/include -I/opt/MATLAB/R2013b/simulink/include -DMATLAB_MEX_FILE -ansi -D_GNU_SOURCE -fPIC -fno-omit-frame-pointer -pthread  -DMX_COMPAT_32 -O -DNDEBUG  "mex_gateway.cpp"

g++ -O -pthread -shared -Wl,--version-script,/opt/MATLAB/R2013b/extern/lib/glnxa64/mexFunction.map -Wl,--no-undefined -o  "mex_gateway.mexa64"  mex_gateway.o  -L./lib/ -lsharedlib -Wl,-rpath-link,/opt/MATLAB/R2013b/bin/glnxa64 -L/opt/MATLAB/R2013b/bin/glnxa64 -lmx -lmex -lmat -lm

我收到以下错误:

mex_gateway.o: In function `mexFunction':
mex_gateway.cpp:(.text+0x24e): undefined reference to `function_from_library(...arguments...)'
collect2: ld returned 1 exit status

    mex: link of ' "mex_gateway.mexa64"' failed.

当然,我对构建命令进行了三重检查,这些命令具有到共享库和库名称的正确路径。共享库确实具有函数的定义:

[user@machine]$ nm lib/libsharedlib.so | grep function_from_library
000000000000198a t __function_from_library__FPCdN51dN27iiiiPdPdPdPdPdPdEND
0000000000001360 T function_from_library__FPCdN51dN27iiiiPdPdPdPdPdPd

那么问题出在哪里?

编辑:我的sharedlibraryheader.h文件如下所示:

#ifndef __SHAREDLIBRARYHEADER_H__
#define __SHAREDLIBRARYHEADER_H__

#ifdef _cplusplus
extern "C"{
#endif

int function1 ( ... );
...
void function_from_library( ... );
...

#ifdef _cplusplus
}
#endif
#endif

2 个答案:

答案 0 :(得分:4)

您必须执行以下操作:

extern "C" {
#include "sharedlibraryheader.h"
}

这将让编译器知道sharedlibraryheader.h中定义的函数符合C ABI而不是C ++ ABI。通常,这是在标题本身中处理的,方式如下:

// Typically put headers outside extern "C"
#include "..."
#include "..."

#ifdef __cplusplus
extern "C" {
#endif

... rest of header here ...

#ifdef __cplusplus
}
#endif

在编译时,您必须对使用共享库 AND 共享库本身的代码执行此操作。

答案 1 :(得分:0)

您知道如果您尝试编译的.cpp文件中没有C ++代码,您实际上可以将它们编译为C源代码(使用GCC)并将其链接到您的C ++项目中吗?在我经常创建的makefile中,我会做类似的事情:

GPPWALL = g++ -Wall -c
GCCWALL = gcc -Wall -c

...

all: glxgraphics.o shadermanager.o sdlkeyboard.o sdlmouse.o main.cpp
    g++ main.cpp LevelGenerator.cpp $(ASSETSOURCE) $(GRAPHICSSOURCE) $(IOSOURCE) $(BASE)AudioManager.cpp -o avgame $(GLUTLIBS) $(GRAPHICSLIBS) $(PTHREADLIBS) $(OPENALLIBS)

...

sdlmouse.o: $(BASE)avg_mouse.c $(BASE)avg_mouse.h
    $(GCCWALL) $(BASE)avg_mouse.c $(GLUTLIBS)

请注意,我已将C编译的代码链接到C ++中,以避免仍然最终C ++代码的“extern C”保护?这是常见的做法。