我有一个共享库`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
答案 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”保护?这是常见的做法。