How to call a function from a shared library?

前端 未结 3 1488
暗喜
暗喜 2020-12-08 01:11

What is the easiest and safest way to call a function from a shared library / dll? I am mostly interested in doing this on linux, but it would be better if there were a plat

3条回答
  •  南方客
    南方客 (楼主)
    2020-12-08 02:10

    NOTE: You are passing C++ objects (in this case STL strings) around library calls. There is no standard C++ ABI at this level, so either try to avoid passing C++ objects around, or ensure that both your library and your program have been built with the same compiler (ideally the same compiler on the same machine, to avoid any subtle configuration-related surprises.)

    Do not forget to declare your exported methods extern "C" inside your library code.

    The above having been said, here is some code implementing what you said you want to achieve:

    typedef std::string (*foo_t)(const std::string);
    foo_t foo = NULL;
    
    ...
    
    # ifdef _WIN32
      HMODULE hDLL = ::LoadLibrary(szMyLib);
      if (!hDll) { /*error*/ }
      foo = (foo_t)::GetProcAddress(hDLL, "foo");
    # else
      void *pLib = ::dlopen(szMyLib, RTLD_LAZY);
      if (!pLib) { /*error*/ }
      foo = (foo_t)::dlsym(pLib, "foo");
    # endif
      if (!foo) { /*error*/ }
    
      ...
    
      foo("bar");
    
      ...
    
    # ifdef _WIN32
      ::FreeLibrary(hDLL);
    # else
      ::dlclose(pLib);
    # endif
    

    You can abstract this further:

    #ifdef _WIN32
    #include 
    typedef HANDLE my_lib_t;
    #else
    #include 
    typedef void* my_lib_t;
    #endif
    
    my_lib_t MyLoadLib(const char* szMyLib) {
    # ifdef _WIN32
      return ::LoadLibraryA(szMyLib);
    # else //_WIN32
      return ::dlopen(szMyLib, RTLD_LAZY);
    # endif //_WIN32
    }
    
    void MyUnloadLib(my_lib_t hMyLib) {
    # ifdef _WIN32
      return ::FreeLibrary(hMyLib);
    # else //_WIN32
      return ::dlclose(hMyLib);
    # endif //_WIN32
    }
    
    void* MyLoadProc(my_lib_t hMyLib, const char* szMyProc) {
    # ifdef _WIN32
      return ::GetProcAddress(hMyLib, szMyProc);
    # else //_WIN32
      return ::dlsym(hMyLib, szMyProc);
    # endif //_WIN32
    }
    
    typedef std::string (*foo_t)(const std::string);
    typedef int (*bar_t)(int);
    my_lib_t hMyLib = NULL;
    foo_t foo = NULL;
    bar_t bar = NULL;
    
    ...
    
      if (!(hMyLib = ::MyLoadLib(szMyLib)) { /*error*/ }
      if (!(foo = (foo_t)::MyLoadProc(hMyLib, "foo")) { /*error*/ }
      if (!(bar = (bar_t)::MyLoadProc(hMyLib, "bar")) { /*error*/ }
    
      ...
    
      foo("bar");
      bar(7);
    
      ...
    
      ::MyUnloadLib(hMyLib);
    

提交回复
热议问题