게으른 상징이 바인딩지 못했습니다:기호는 찾을 수 없
-
20-12-2019 - |
문제
나는 세 가지는 헤더 파일 내 프로젝트 는 개체에 대해 설명합니다 Rational
, Complex
, 고 RubyObject
.처음 두 템플릿이 있습니다.모든태로 되돌릴 수 있을 사용하여 복사본을 생성자,정의되는 헤더에 파일을 제외하고는 사람들을 위해 구축 Rational
고 Complex
서 const RubyObject&
s 정의 에 소스 파일.
참고: 그 정의가 필요합니다.면 모든 go 헤더에서,당신 원형 종속성.
A while back,I ran 로 몇 가지 해결되지 않은 상징류 두 개의 복사본을 생성자를 정의한 소스 파일에서입니다.할 수 있었을 포함한 원본 파일에서 다음과 같은 기능
void nm_init_data() {
nm::RubyObject obj(INT2FIX(1));
nm::Rational32 x(obj);
nm::Rational64 y(obj);
nm::Rational128 z(obj);
volatile nm::Complex64 a(obj);
volatile nm::Complex128 b(obj);
}
다음 전화 nm_init_data()
라이브러리에서 입국 지점에서 주요 소스 파일.이렇게 강제로 이러한 기호 연결되는니다.
불행하게도,나는 최근 업그레이드 GCC 및 오류가 돌아왔다.사실,그것은에서 일어나는 약간 다른 곳으로 GCC4.6 (예를 들어,에서 트라비스-CI).
하지만 그에 버전 특유의 문제는(내가 생각하기 전에).우리는 그것을 참조하십시오에 트래비스 CI 의 우분투를 기반 시스템, 실행되는 GCC4.6.그러나 우리는 그것을 보지 않 우분투에서는 기계와 함께 하는 GCC4.8.1 또는 4.8.2.하지만 우리는 마 에서 볼 Mac OS X 기계 4.8.2—와 동일하지 않기로 4.7.2.을 끄는 최적화되지 않 도울 것으로 보인다.
실행하는 경우 nm
에는 도서관,기호가 확실히 정의되지 않은:
$ nm tmp/x86_64-darwin13.0.0/nmatrix/2.0.0/nmatrix.bundle |grep RationalIsEC1ERKNS
U __ZN2nm8RationalIsEC1ERKNS_10RubyObjectE
00000000004ca460 D __ZZN2nm8RationalIsEC1ERKNS_10RubyObjectEE18rb_intern_id_cache
00000000004ca458 D __ZZN2nm8RationalIsEC1ERKNS_10RubyObjectEE18rb_intern_id_cache_0
나는 이 두 가지 정의 항목을 있는 하위를 정의되지 않은 상징하지만,나도 많이 알고 싶에 대한 컴파일러입니다.
도 사본을 생성자 정의되지 않은 기호의 각 버전 Rational
템플릿:
__ZN2nm8RationalIiEC1ERKNS_10RubyObjectE
__ZN2nm8RationalIsEC1ERKNS_10RubyObjectE
__ZN2nm8RationalIxEC1ERKNS_10RubyObjectE
"글쎄,그의 이상한,"나는 생각했다."Complex64
고 Complex128
라고도서 nm_init_data
기능,그러나 그들은 모두 해결이 제대로와에 나열되지 않은 nm -u
출력." 그래서 나도 추가 volatile
기 전에 합리적인 사본을 건설뿐만 아니라고 생각하고,어쩌면 컴파일러 최적화하는 뭔가가 우리가 원하지 않는 최적화되니다.그러나지 않았던 그것을 해결하거나,도 같은 지역에 있습니다.더 보기이와 함께,주의해야 할 점은:
void nm_init_data() {
volatile VALUE t = INT2FIX(1);
volatile nm::RubyObject obj(t);
volatile nm::Rational32 x(const_cast<nm::RubyObject&>(obj));
volatile nm::Rational64 y(const_cast<nm::RubyObject&>(obj));
volatile nm::Rational128 z(const_cast<nm::RubyObject&>(obj));
volatile nm::Complex64 a(const_cast<nm::RubyObject&>(obj));
volatile nm::Complex128 b(const_cast<nm::RubyObject&>(obj));
}
주의해야 할 점은 이제 내가 똑같은 오류가 있지만,복잡한 물체를 대신 합니다.아!
dyld: lazy symbol binding failed: Symbol not found: __ZN2nm7ComplexIdEC1ERKNS_10RubyObjectE
Referenced from: /Users/jwoods/Projects/nmatrix/lib/nmatrix.bundle
Expected in: flat namespace
dyld: Symbol not found: __ZN2nm7ComplexIdEC1ERKNS_10RubyObjectE
Referenced from: /Users/jwoods/Projects/nmatrix/lib/nmatrix.bundle
Expected in: flat namespace
이것은 완전히 터무니없는 것입니다.에 대한 정의는 다음과 같습니다 이 두 기능은 동일한 원본 파일 nm_init_data()
기능:
namespace nm {
template <typename Type>
Complex<Type>::Complex(const RubyObject& other) {
// do some things
}
template <typename Type>
Rational<Type>::Rational(const RubyObject& other) {
// do some other things
}
} // end of namespace nm
힌트: 하는 것은 언급 할 가치가있는 오류가 발생하지 않을 때 nm_init_data()
가 호출됩니다(i.e,할 때 라이브러리드).그것은 훨씬 나중에 발생하는 동안,다른 통화를 이러한 성가신 기능입니다.
어떻게 이 문제를 해결하고 한번에 모든 및 다른 사람이 그것을 좋아합니까?
해결책
당신이 요구하는 다음과 같은 난다.
그 정의가 필요합니다.면 그들 모두는 헤더에서,당신은 원형을 의미할 수 있습니다.
대부분의 경우에 해결할 수 있는 그러한 원형 얽힘을 분리하여 당신의 코드를 추가.hpp 파일와 함께 포함되어 있는 클래스 정의를 포함하는 템플릿 정의를 어디서나 필요합니다.
는 경우에는 코드는 실제 원형 종속,그것은 컴파일되지 않습니다.일반적으로,당신의 종속성을 것 원형이고,당신은 가까이 갈 방법은 수준을 확인하고 그들의 요구를 모두 형식을 컴파일.
그래서 될 수 있다는 당신의 유형을 사용하여 다음을 컴파일 모두 하나입니다.cpp 파일(예를들면을 통해 세 가지입니다.hpp 포함).나만 있 포인터를 다른 형식,다음 사용 앞으로 선언하는 보장하기 위해,모든 템플릿은 해결됩니다.또는 셋째,당신이 할 수있는 몇 가지 방법에 따라 달라지는 앞으로 어떤 따라 달라지는 뒤에,하나의 종류 중 하나에서 파일,다른 종류에 다른,그리고 당신이 표시됩니다.
또한,그것은 당신이 사용해야 하는 앞으로 선언에 대한 귀하의 누락된 항목.제가 기대하는 것과 같은 후에 다음의 정의는 기능입니다.E.g.:
template nm::Complex<nm::RubyObject>::Complex(const nm::RubyObject& other);
다른 팁
Rational
,Complex
...는 템플릿사본을 생성자...에 정의된 헤더 파일을 제외하고는 사람들을 위해 구축
Rational
고Complex
서const RubyObject&
s 에 정의되어 있는 원본 파일입니다.
그 안에 당신의 문제입니다.이 Rational
고 Complex
는 템플릿 모든 그들의 방법을 사용할 수 있어야에서 당신의 헤더 파일.
하지 않는 경우,그 다음 가끔 수 있습니다 얻을 수있다 그것으로 순서에 따라하는 것은 불과합하는 순서는 것이 연결되어-하지만 더 자주 당신을 얻을 것 이상의 오류에 대한 정의되지 않은 기호는 무슨 일이 일어나고 있는지 정확히 여기입니다.
단순히 움직임의 정의 Rational(const RubyObject&)
고 Complex(const RubyObject&)
으로 각각의 헤더를 모든 작동해야 합니다.