편집 : 승인 된 답변 아래의 댓글은 Android 동적 로더에 문제가 있음을 보여줍니다.동적 라이브러리의 정적 * 템플릿 * 클래스 멤버
정적 멤버가있는 템플릿 클래스의 헤더가 있습니다. 런타임시 정적 멤버의 주소는 라이브러리 및 클라이언트 코드에서 사용됩니다. 템플리트는 라이브러리와 클라이언트 코드에서 내재적으로 인스턴스화됩니다. 그것은 Linux와 OSX에서 잘 작동하지만 심볼은 복제되지만 nm으로 표시된 것처럼 "uniqued"로 표시됩니다 (아래 참조). 그러나 ARM (Android) 용으로 컴파일하면 심볼이 DSO 및 실행 파일에서 weak로 표시됩니다. 로더가 통합되지 않으며 런타임에 심볼이 효과적으로 복제됩니다! two instances of a static member, how could that be? Static template data members storage 특히이 답변 : https://stackoverflow.com/a/2505528/2077394 과 :
나는이 읽을 http://gcc.gnu.org/wiki/Visibility을하지만, 난 여전히 조금 의아해입니다. 가시성을위한 속성이 최적화하는 데 도움이되는 것으로 알고 있지만 기본적으로 제대로 작동해야한다고 생각했습니다. 나는 C++ 표준이 공유 라이브러리를 신경 쓰지 않는다는 것을 알고 있지만 공유 라이브러리를 사용하면 표준을 깨뜨리는 것을 의미합니까? (또는 적어도이 구현은 C++ 표준을 준수하지 않습니다.) 보너스 : 어떻게 고칠 수 있습니까?
template<class T>
struct TemplatedClassWithStatic {
static int value;
};
template<class T>
int TemplatedClassWithStatic<T>::value = 0;
shared.cpp :
#include "TemplateWithStatic.hpp"
int *addressFromShared() {
return &TemplatedClassWithStatic<int>::value;
}
MAIN.CPP :
#include "TemplateWithStatic.hpp"
#include <cstdio>
int *addressFromShared();
int main() {
printf("%p %p\n", addressFromShared(), &TemplatedClassWithStatic<int>::value);
}
그리고 건물
헤더 (및 템플릿을 사용하지 않는 것은 :) 허용 대답하지 않습니다) , 기호 정의를 살펴보면 :
.so를 제조 :
g++-4.8 -shared src/shared.cpp -o libshared.so -I include/ -fPIC
컴파일 메인 링크 :
g++-4.8 src/main.cpp -I include/ -lshared -L.
가
심볼 "고유"로 표시되어
nm -C -A *.so a.out | grep 'TemplatedClassWithStatic<int>::value'
libshared.so:0000000000200a70 u TemplatedClassWithStatic<int>::value
a.out:00000000006012b0 u TemplatedClassWithStatic<int>::value
가
~/project/android-ndk-r9/toolchains/arm-linux-androideabi-4.8/prebuilt/darwin-x86_64/bin/arm-linux-androideabi-g++ -o libshared.so src/shared.cpp -I include/ --sysroot=/Users/amini/project/android-ndk-r9/platforms/android-14/arch-arm/ -shared
를 .so를 제조 컴파일 및 링크 주
~/project/android-ndk-r9/toolchains/arm-linux-androideabi-4.8/prebuilt/darwin-x86_64/bin/arm-linux-androideabi-g++ src/main.cpp libshared.so -I include/ --sysroot=${HOME}/project/android-ndk-r9/platforms/android-14/arch-arm/ -I ~/project/android-ndk-r9/sources/cxx-stl/gnu-libstdc++/4.8/include -I ~/project/android-ndk-r9/sources/cxx-stl/gnu-libstdc++/4.8/libs/armeabi-v7a/include -I ~/project/android-ndk-r9/sources/cxx-stl/gnu-libstdc++/4.8/include/backward -I ~/project/android-ndk-r9/platforms/android-14/arch-arm/usr/include ~/project/android-ndk-r9/sources/cxx-stl/gnu-libstdc++/4.8/libs/armeabi-v7a/libgnustl_static.a -lgcc
기호가 약합니다!
nm -C -A *.so a.out | grep 'TemplatedClassWithStatic<int>::value'
libshared.so:00002004 V TemplatedClassWithStatic<int>::value
a.out:00068000 V TemplatedClassWithStatic<int>::value
편집, 문맥에 대한 참고 : 나는 OOLua, 루아 내 unittests에 ++ 바인딩 C를 돕는 라이브러리 놀고 있었는데 나는 안드로이드를 대상으로 시작 실패했을 때. 나는 코드를 "소유"하지 않고 차라리 깊이 수정하려고한다.
편집, 안드로이드에서 실행합니다 :
이adb push libshared.so data/local/tmp/
adb push a.out data/local/tmp/
adb shell "cd data/local/tmp/ ; LD_LIBRARY_PATH=./ ./a.out"
0xb6fd7004 0xb004
감사. 공유 라이브러리를 사용하기 시작하면 안드로이드 툴체인이 완전한 C++ 표준을 지원하지 않는다고 결론을 맺어야합니까? – Joky
"안드로이드 툴체인은 공유 라이브러리를 사용하기 시작하면 C++ 표준을 완벽하게 지원하지 않습니다."- 약한 심볼을 사용하여 실험 한 결과 (Linux에서) 공유 라이브러리에서 실제로 정적 데이터를 처리하는 것으로 나타났습니다. 즉, 링커는 약한 기호 중 하나만 사용하도록 강제하고 다른 인스턴스는 무시됩니다. 프로그램을 실행하려고 시도 했습니까? –
예, 인쇄 된 주소가 다릅니다 (Android에서만) – Joky