来自 MATLAB Mex 库的链接错误
Posted
技术标签:
【中文标题】来自 MATLAB Mex 库的链接错误【英文标题】:Linking errors from MATLAB Mex library 【发布时间】:2013-03-08 16:23:42 【问题描述】:我在编译 MATLAB Mex 库时遇到了麻烦 - 特别是来自 this website 的“相关聚类优化”代码。
我正在尝试在 OSX 机器上编译,并且正在使用提供的 mexall
函数。这运行以下行:
mex -O -largeArrayDims CXXFLAGS="\$CXXFLAGS -Wno-write-strings" QPBO.cpp QPBO_extra.cpp QPBO_maxflow.cpp QPBO_wrapper_mex.cpp QPBO_postprocessing.cpp -output QPBO_wrapper_mex
错误发生在链接时与 MATLAB 命令行的以下输出:
ld: duplicate symbol QPBO<int>::GetMaxEdgeNum() in QPBO_extra.o and QPBO.o
collect2: ld returned 1 exit status
mex: link of ' "QPBO_wrapper_mex.mexmaci64"' failed.
由此判断,GetMaxEdgeNum
函数同时出现在QPBO_extra.o
和QPBO.o
中。但是,它实际上只是在头文件QPBO.h
中定义。因此,我怀疑包含它的两个源文件都将它作为符号包含在其目标文件中,从而导致链接时出现问题。
(更多信息:每个源文件还在文件的最结尾处包含一个文件#include "instances.inc"
。instances.inc
显然似乎包含模板化QPBO
的一些特定实例。)
我在这里犯了一个明显的错误吗?我可以做些什么来增加编译这段代码的机会?
编辑
这是QPBO.h
中有问题的GetMaxEdgeNum
函数的定义:
template <typename REAL>
inline int QPBO<REAL>::GetMaxEdgeNum()
return (int)(arc_max[0]-arcs[0])/2;
编辑 2
关于我的机器的更多细节:
OSX 10.6.8 MATLAB R2012a(也有 R2011b) g++ 4.2 或 g++ 4.0(或通过 MacPorts 的 g++ 4.6)我在下面的“赏金描述”中添加了一些关于我真正想要的答案的详细信息。
编辑 3
大家一致认为instances.inc
可能是造成问题的原因。这包含在每个cpp
文件的末尾,它包含以下内容:
#include "QPBO.h"
#ifdef _MSC_VER
#pragma warning(disable: 4661)
#endif
// Instantiations
template class QPBO<int>;
template class QPBO<float>;
template class QPBO<double>;
template <>
inline void QPBO<int>::get_type_information(char*& type_name, char*& type_format)
type_name = "int";
type_format = "d";
template <>
inline void QPBO<float>::get_type_information(char*& type_name, char*& type_format)
type_name = "float";
type_format = "f";
template <>
inline void QPBO<double>::get_type_information(char*& type_name, char*& type_format)
type_name = "double";
type_format = "Lf";
【问题讨论】:
有趣的是,它来自@Shai 的网站,所以你有自己的第一手支持来源:) 是的,我直接联系了他,但他说他没有在 OSX 上编译的经验。失败的部分实际上是第三方库,所以正如我在下面所说的,我认为理想情况下我应该有 OSX 的人来帮助解决这个问题...... 如果您能粘贴instances.inc
中的 QPBO 模板的特化,这可能会有所帮助。 (只是这些函数的原型应该没问题,我其实不需要看它们的代码内容。)
@BillCheatham - 我怀疑问题与instaces.inc
文件有关。你能把它和qbpo.*
中的save
方法去掉吗(它不用于大规模CC)。
谢谢@Shai 我试了一下,但现在我发现链接失败是因为从 QPBO_wrapper 引用的未定义符号:Undefined symbols: "QPBO<int>::Solve()", referenced from: void QPBO_wrapper...
等。我同意我认为instances.inc
很麻烦!
【参考方案1】:
问题似乎是某些模板代码位于 .cpp 文件中。
-
从
.cpp
文件中删除#include instances.inc
声明。
从 QPBO.cpp、QPBO_extra.cpp、QPBO_maxflow.cpp 和 QPBO_postprocessing.cpp 中移动所有代码到头文件qpbo.h。
您现在将拥有一个 .cpp 文件 qpbo_wrapper_mex.cpp 和一个标头 qpbo.h
mex 文件(在 matlab 中)使用:
>> mex -O -largeArrayDims qpbo_wrapper_mex.cpp
应该可以...
【讨论】:
太好了,这行得通。感谢您的工作......在图书馆和为我解决这个问题! @Shai +1 给你,先生,以及当之无愧的赏金。我毫不怀疑你能解决这个问题:)【参考方案2】:将GetMaxEdgeNum
更改为静态函数,或将其放入匿名命名空间可能会解决您的问题。
正如您所建议的,原因是它在两个目标文件中都有外部链接,这会导致名称冲突。我建议的解决方案为其提供了内部链接。
修改后:
如果您在类定义中定义方法,它会改变什么吗? 像这样:
template <typename REAL>
class QPB0
...
public:
inline int GetMaxEdgeNum()
return (int)(arc_max[0]-arcs[0])/2;
...
;
【讨论】:
谢谢,我试了一下(在函数中int
之前添加了单词 static
- 请参阅问题编辑)。但是,我收到了一些关于cannot declare member function 'int QPBO<REAL>::GetMaxEdgeNum()' to have static linkage
的错误。我不确定这意味着什么。
这意味着我的回答只有在你的函数不是成员函数时才有效,我认为它不是。 inline 关键字应该有同样的作用,所以我不知道为什么会出现链接器错误。
谢谢,我已经尝试过了,它绝对应该可以工作——只是不行。我仍然收到相同的链接器错误。不太确定下一步该做什么,但我会尝试一些不同的包含或编译器选项。我认为问题的一部分是每个源文件底部包含的奇怪的instances.inc
...以上是关于来自 MATLAB Mex 库的链接错误的主要内容,如果未能解决你的问题,请参考以下文章
MATLAB + Mex + OpenCV:链接和编译正确,但在运行时找不到库