5

我有一个名为 NMatrix 的库(技术上是 Ruby 扩展),它是用 C 和 C++ 编写的。它使用 C++ 模板来管理不同的类型,例如,Rational128Rational64. 它也有RubyObject和。我通过在目标文件中创建一些模板版本来强制构建这些模板版本——在从库入口点调用的函数中。Complex64Complex128

它在 GCC 4.7 中工作得很好,但是当我在 Travis-CI 上编译时,它在运行时遇到一个未定义的符号错误

exposes cblas rot /home/travis/.rvm/rubies/ruby-2.0.0-p247/bin/ruby: symbol lookup error: /home/travis/build/SciRuby/nmatrix/lib/nmatrix.so: undefined symbol: _ZN2nm7ComplexIfEC1ERKNS_10RubyObjectE

未定义的符号是nm::Complex::Complex(nm::RubyObject const&),它是显式定义和实例化的(见下文)。

这是一个精简版data.cpp

#include "data.h"

void nm_init_data() { // called from library entry point
  // These force the compiler to build these versions of the typedef'd templates.
  // I think this is a gross way to do it, but can't find a better idea.
  nm::RubyObject obj(INT2FIX(1));
  nm::Rational32 x(obj);
  nm::Rational64 y(obj);
  nm::Rational128 z(obj);
  nm::Complex64 a(obj);    // Clear instantiation of the undefined symbol
  nm::Complex128 b(obj);
}

data.h就像这样:

#include "nmatrix.h"

#include "complex.h" // classes are all declared in headers
#include "rational.h"
#include "ruby_object.h"

void nm_init_data();

nmatrix.cpp是声明库入口点的地方。相关部分如下所示:

void Init_nmatrix() {
  // declarations of Ruby-exposed functions here, e.g., 
  rb_define_method(cNMatrix, "initialize", (METHOD)nmatrix_constructor, -1);

  nm_init_data();
}

那么我做错了什么?为什么这适用于 GCC 4.7.1(所有规范都通过),但不适用于 4.6.3?它是一个错误吗?(如果是错误,是否有解决方法?)

如果你很好奇,相关文件的完整版本在这里

4

0 回答 0