c++shared-librariesshared-memoryandroid-make

Share single copy of structure/data defined in shared library to different objects defined in multiple shared libraries


Language: C++/C Android Makefile System: https://developer.android.com/ndk/guides/android_mk

I have an application which open a shared library foo.so and within foo.so we open three other shared libraries bar1.so, bar2.so and bar3.so in three different threads (pthread_create) but in same application/process. pid is same, thread id is different for bar1, bar2, bar3

Each of bar1.so, bar2.so, bar3.so have Entry functions which are called using dlsym after dlopen and different types of objects are created within bar1 2 3.so libs

bar1.so, bar2.so and bar3.so also have dynamic linking to another shared library called baz.so which has some common structs/routines. baz.so Not explicitly 'dlopen' ed. In make files of bar1.so, bar2.so, bar3.so I specify baz.so as a shared library which it needs. I want to create a singleton structure in baz.so where each of bar1.so, bar2.so and bar3.so can write and read to/from.

I tried creating a static object in baz.so but bar1.so, bar2.so and bar3.so seems to get their distinct copies of the structure. Its not shared. By Distinct copies i mean that according to code snippet below, when I read in bar2.so , sharedData.a is 10 and not 22

baz.so: 
Filename: sharedobject.h -> All code is defined in sharedobject.h file in baz.so
struct Config {
    int a;
    bool b;
    // Constructor
    Config (int val1, bool val2) {
        a = val1;
        b = val2;
    }
};
class SharedObject {
public:
    Config sharedData;
    SharedObject() {
       // Initialize some common data here which will be read
       // and written to
       sharedData.a = 10;
       sharedData.b = 20;
    }
    static SharedObject* GetInstance() {
        static SharedObject singletonObjectInstance;
        return &singletonObjectInstance;
    }
    // Data update function called by either of bar1, bar2 or bar3.so 
    static void UpdateData(Config &data) {
        // Lock : Proper Locking is there but not shown in code
        SharedObject::GetInstance()->sharedData.a = data.a;
        // Unlock
    } 
}
Android.mk:
LOCAL_SRC_FILES :=  // Empty fields 
LOCAL_INC_FILES :=  // Empty Fields
LOCAL_MODULE := baz
include $(BUILD_SHARED_LIBRARY) # This will build baz.so
bar1.so: Let's say Thread1 under ProcessX updates some data
Filename: classx.cpp
#include "sharedobject.h"
   void ClassX::WriteToCommonData() {
      SharedObject *pSharedObject= SharedObject::GetInstance();
      print("Object Address:%p", pSharedObject); // These addresses are not same in bar1 and bar2 which is the problem
      Config data(22, false);
      SharedObject::UpdateData(data);
   }
In Android.mk of bar1.so
Linking is done by specifying shared lib: -> https://developer.android.com/ndk/guides/android_mk#local_shared_libraries
LOCAL_SRC_FILES := classx.cpp
LOCAL_SHARED_LIBRARIES := baz.so
LOCAL_CFLAGS :=   # No Special flags used.
LOCAL_MODULE := bar1
include $(BUILD_SHARED_LIBRARY) # This will build bar1.so 

bar2.so: Lets's say Thread2 under same ProcessX wants to read it now
Filename: classy.cpp
#include "sharedobject.h"
   void ClassY::ReadFromCommonData() {
       SharedObject *pSharedObject= SharedObject::GetInstance();
       print("Object Address:%p", pSharedObject); // These addresses are not same in bar1 and bar2 which is the problem
       // Read values updated by bar1.so
       print(pSharedObject->sharedData.a); // It is 10, not 22
   } 
In Android.mk

LOCAL_SHARED_LIBRARIES := baz.so
LOCAL_SRC_FILES := classy.cpp
LOCAL_CFLAGS :=   # No Special flags used.
LOCAL_MODULE := bar2
include $(BUILD_SHARED_LIBRARY) # This will build bar2.so 

Even though all bar libraries are under same Process, do I still need to use Shared memory APIs ?

I have checked these links but it does not seem to answer my question: how to share a single shared library(*.so) instance between two applications Shared Library Structure


Solution

  • class __attribute__ ((visibility ("default")) SharedObject
    

    Defining the class as above solved the issue. It seems like without this, symbol is not exported and not available for dynamic linker.