dynamic_cast doesn't work across module boundaries on clang - android

I am seeing a very strange failure that is very similar to the problem described in
dynamic_cast on llvm clang compiler failing: dynamic_cast returns nullptr when I am trying to downcast from base type to derived type, for an object of derived type. In my case though typeid actually shows the same dynamic type.
Below is the debug function that I use to verify run-time types. It takes a pointer of SrcType* and tries to dynamically cast it to pointer of DstType*. If conversion fails, i.e. the returned pointer is nullptr, it prints an error message. VERIFY() macro checks if condition is true:
template<typename DstType, typename SrcType>
void CheckDynamicType( SrcType *pSrcPtr )
{
VERIFY(dynamic_cast<DstType*> (pSrcPtr) != nullptr,
"Dynamic type cast failed. Src typeid: \'", typeid(*pSrcPtr).name(),
"\' Dst typeid: \'", typeid(DstType).name(), '\'');
}
And here is the output that I am getting:
Dynamic type cast failed. Src typeid: 'N8Diligent15RefCountersImplE' Dst typeid: 'N8Diligent15RefCountersImplE'
I am using clang compiler from Android ndk r16 toolchain. I am compiling with rtti flag. The same code works fine on gcc and msvc.
Another bit of information: the code also works fine if I build it with gnustl runtime (I am not sure how gnu stl works with clang, but anyway).
UPDATE
After spending few more hours looking into the issue I found out that dynamic_cast fails when it is used on the object created in another module.
From this
Using clang++, -fvisibility=hidden, and typeinfo, and type-erasure and this posts it looks like dynamic_cast should work if the class is labeled with __attribute__((visibility("default"))) so that typeid structures from two modules will be merged. This, however does not help either and I am still seeing the issue.

If you’re using the stock system compiler there’s a near 0 chance dynamic_cast of the compiler isn’t working. This is tested and used extensively in everything from system software up.

Related

Unordered_map declaration throws error with NDK (clang), works fine with gcc

I'm trying to run a C++ project on Android. The following statement appears in one of the source files (part of a big project).
std::unordered_map <int, std::shared_ptr<Frame>, std::hash<int>, std::equal_to<int>,
Eigen::aligned_allocator< std::pair<const int, std::shared_ptr<Frame> > > > idToKeyFrame;
The NDK build complains the following
sysroot/usr/include/c++/v1/unordered_map:1684:5: error: static_assert failed due to requirement 'is_same<value_type, typename allocator_type::value_type>::value' "Invalid allocator::value_type"
I cannot spot what part of declaration is incompatible. Please help in fixing this error.
cplusplus.com reference
Update
When I modify the allocator (as suggested in comment by Marc) to Eigen::aligned_allocator<std::pair<int, std::shared_ptr<Frame>>> The error message remains the same but line number changes
sysroot/usr/include/c++/v1/unordered_map:854:5: error: static_assert failed due to requirement 'is_same<value_type, typename allocator_type::value_type>::value' "Invalid allocator::value_type"
Update++
According to this answer :
libstdc++ does not static_assert, libstdc++ ignores the exact type of the allocator and rebinds it to the container's value type.
and
Clang/libc++ are not forgiving
Yet another Update
I have been able to go past the error by commenting out the line in the source for unordered_map. This is a resort for now (until I get a solution).

Android NDK C++ error : 'memmove' was not declared in this scope

In android ndk c++ in visual studio, I'm trying to use memmove.
The compiler throws:
error : 'memmove' was not declared in this scope, and no declarations were found by argument-dependent lookup at the point of instantiation
I include string.h so, I don't get what I am missing here...
I inspected the string.h and found that the definition of memmove in string.h in the ndk is inside a preprocessor block
#if defined(__BIONIC_FORTIFY)
And is undefined.
I don't know what is this preprocessor and why it is preventing the memmove from being defined.
What is this __BIONIC_FORTIFY thing? is it safe to define?
Is there a problem using memmove in android?
My research : this preprocessor is defined by
#define _FORTIFY_SOURCE
but adding this to my build does not get rid of the error.

NEON intrinsic types work in C but throw invalid arguments error in C++

I have problems with using NEON intrinsics and inline assembly in Android NDK.
NEON types like float32x4_t give an "invalid arguments" error when compiling C++ code with GCC 4.6 and 4.8, however, the code compiles fine if compiled as C.
For example, here's some code:
inline float32x4_t VectorAdd(float32x4_t a, float32x4_t b)
{
return vaddq_f32(a, b);
}
I get two errors here:
In the function itself: Invalid arguments ' Candidates are: ? vaddq_f32(?, ?) '.
Where the function is called: Invalid arguments ' Candidates are: ? VectorAdd(?, ?) '.
All NEON types are displayed as ? in the error message, while non-NEON types are displayed correctly.
What is also strange is that functions which only use NEON types as return values (for example, vld1q_f32 and my abstract wrapper of it) don't suffer from the error.
I tried the same code in GCC Explorer 4.6 and 4.5, and there is no error, and correct and optimized assembly is generated, however, it doesn't work with Android NDK.
As a workaround, in Window / Preferences / C/C++ / Code Analysis, set the Severity of "Invalid Arguments" errors to Warning, so that these bogus errors won't prevent launching the application.

Getting rid of wchar_t size linker warning

I compile my Android NDK library with -fshort-wchar. I know the RTL assumes 4-byte wchar_t, I know what I'm doing, the library works. However, on every build linker gives me the following warning for every object file:
ld.exe: warning: MyFile.o uses 2-byte wchar_t yet the output is to use 4-byte wchar_t; use of wchar_t values across objects may fail
When I provide
LOCAL_LDLIBS := --no-wchar-size-warning
This gives me an "unrecognized option" error.
Adding APP_LDFLAGS += -Wl,--no-wchar-size-warning (to Application.mk) works fine for me on NDKs at least as early as r7.
I assume it would work just the same as:
LOCAL_LDLIBS := -Wl,--no-wchar-size-warning
Have you seen this? The post explains that the --no-wchar-size-warning option will make the linker treat the mismatch as a warning, not an error. As in the enum case, the authors choose to display the message anyway.
You don't see the effect of setting this flag in your project because as detailed elsewhere, using -fshort-wchar automatically adds -Wl,--no-wchar-size-warning.

dlsym returning symbol not found in android after succesful return of dlopen

I am loading one shared library from another. Lets say foo2.so from foo1.so
I am using dlopen followed by dlsym
dlopen succeed with proper handle but dlsym returns with "symbol not found" error .I have used dlerror to print the error.
These are the things i tried. In foo2.so .mk file I added
LOCAL_LDFLAGS += -Wl,--export-dynamic.
I checked the symbol in foo2.so using nm and it is there.
Both the modules are in C except one wrapper file in foo1.so which is in C++, Calling file is in C.
Can any one suggest whether i missed any thing . I am running this on android emulator on froyo.
I would be tempted to poke around at the implementation level and verify things. Look in /proc/PID#/maps and make sure both libraries are loaded.
objdump both caller and callee and make sure that C++ bit didn't mangle the name.
Are you using a suitable RTLD_ flag, and is dlsym getting a valid handle returned by dlopen ?
Can you build (a simplified version of) the two libraries and test executable for a desktop linux or cygwin in order to make sure what you want to do is generally workable - ie, that the problem is android-specific?

Categories

Resources