"NumericArray" and its instantiations are not exported and causes issue on Android when `-fvisibility=hidden` is used
- Dominant language
- C++
- Stars
- 17.1k
- Forks
- 4.3k
- Avg merge
- 3d 13h
- Merged PRs (30d)
- 88
Description
### Describe the bug, including details regarding any error messages, version, and platform.
Currently, the `ARROW_EXPORT` attribute is not added for class `NumericArray`, nor its instantiation classes, and it causes issue on Android when `-fvisibility=hidden` is used.
If an application is linked with `libarrow.so`, a `NumericArray` object created inside `libarrow.so` seems to be considered as a different type than `NumericArray` type used in the application. Therefore, operations like `dynamic_cast` or `dynamic_pointer_cast` will fail.
Here is a specific example:
```
#include
#include "arrow/array/array_primitive.h"
#include "arrow/array/util.h"
int main()
{
auto array = *MakeArrayOfNull(arrow::uint64(), 100);
auto uint64_array = std::dynamic_pointer_cast(array);
if (uint64_array)
{
printf("dynamic_cast is successful\n");
}
else
{
printf("dynamic_cast failed\n");
}
return 0;
}
```
Note that `MakeArrayOfNull(arrow::uint64(), 100)` causes arrow library to generate a `NumericArray` (aka `UInt64Array`) object, and coverts it to its base class pointer `Array`, then return it. Then the app tries to cast it back to `UInt64Array`, but on Android, the operation fails, i.e. the output is `dynamic_cast failed`.
This is only observed on Android. It doesn't happen on Linux. Initially I thought it's because of compiler difference, as Android uses Clang. But I then observed that even if I use Clang to build both arrow and the sample app on Linux, the issue won't reproduce. So it might be related to the dynamic linker implementation difference on Android and Linux.
I also noticed that if `ARROW_EXPORT` is added for `class NumericArray` declaration in `arrow/cpp/src/arrow/type_fwd.h` ([code](https://github.com/apache/arrow/blob/main/cpp/src/arrow/type_fwd.h#L188)), then the issue goes away. However, it doesn't work if we the export at class defination in `arrow/cpp/src/arrow/array/array_primitive.h` ([code](https://github.com/apache/arrow/blob/main/cpp/src/arrow/array/array_primitive.h#L87)), maybe because it's a template class and the declarations of instantiations like `UInt64Array` are in `arrow/cpp/src/arrow/type_fwd.h` ([code](https://github.com/apache/arrow/blob/main/cpp/src//arrow/type_fwd.h#L196-L215)).
### Component(s)
C++
Contributor guide
Research direction
Start with the NumericArray declaration and instantiation declarations in cpp/src/arrow/type_fwd.h, then compare them with the template definition in cpp/src/arrow/array/array_primitive.h. Reproduce the dynamic_pointer_cast failure on Android with -fvisibility=hidden using the MakeArrayOfNull example. Done means the generated numeric array types can be cast back successfully from an application linked to libarrow.so.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- android, cpp
- Domain
- mobile-dev
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100