From 2ae5db35b0da3eb947b066185a99219ec3c09a5c Mon Sep 17 00:00:00 2001 From: Pablo Marcos Date: Fri, 27 Jun 2014 00:29:49 +0200 Subject: [PATCH] Hack to make RCCpp work on Linux. We need to change the name of the library every time we call dlopen because otherwise even after closing it dlopen returns the same handler. --- Source/Engine/RCCpp/RCCppUnix.cpp | 29 ++++++++++++++++++++++++++--- Source/Engine/RCCpp/RCCppUnix.h | 2 ++ Source/Engine/RCCpp/RCCppWin.cpp | 6 ++++++ 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/Source/Engine/RCCpp/RCCppUnix.cpp b/Source/Engine/RCCpp/RCCppUnix.cpp index 87a8d90b542..90155de1a6a 100644 --- a/Source/Engine/RCCpp/RCCppUnix.cpp +++ b/Source/Engine/RCCpp/RCCppUnix.cpp @@ -1,4 +1,4 @@ -// +// // Copyright (c) 2008-2014 the Urho3D project. // // Permission is hereby granted, free of charge, to any person obtaining a copy @@ -40,7 +40,8 @@ RCCppUnix::RCCppUnix(Context* context) : library_(NULL), createObject_(NULL), destroyObject_(NULL), - compiler_(new RCCppGppCompiler(context_)) + compiler_(new RCCppGppCompiler(context_)), + fileSystem_(context_->GetSubsystem()) { } @@ -84,7 +85,23 @@ void RCCppUnix::DestroyObject(RCCppObject *object) bool RCCppUnix::LoadLib(const String& libraryPath) { + if (library_ != NULL) + { + UnloadLib(); + } +#ifdef __linux__ + // Hack in case it's Linux. It seems dlopen caches the library name and in case + // the same library name is opened again (even after closing the library), it returns + // the same handler (memory address). Hence, every time we need to load the library we + // use a different name to avoid that happening. + static unsigned counter = 0; + String tmpLibraryPath = libraryPath + "." + String(counter++); + fileSystem_->Rename(libraryPath, tmpLibraryPath); + library_ = dlopen(tmpLibraryPath.CString(), RTLD_LAZY); + fileSystem_->Rename(tmpLibraryPath, libraryPath); +#else library_ = dlopen(libraryPath.CString(), RTLD_LAZY); +#endif if (library_ != NULL) { String name = GetFileName(libraryPath); @@ -94,6 +111,7 @@ bool RCCppUnix::LoadLib(const String& libraryPath) } else { + LOGERROR("Error loading library " + libraryPath + ": " + dlerror()); return false; } } @@ -102,9 +120,14 @@ void RCCppUnix::UnloadLib() { if (library_ != NULL) { - dlclose(library_); + if (dlclose(library_) != 0) + { + LOGERROR("Error closing library: " + String(dlerror())); + } library_ = NULL; mainObject_ = NULL; + createObject_ = NULL; + destroyObject_ = NULL; } } diff --git a/Source/Engine/RCCpp/RCCppUnix.h b/Source/Engine/RCCpp/RCCppUnix.h index ebda01d14c5..6e89d6e3131 100644 --- a/Source/Engine/RCCpp/RCCppUnix.h +++ b/Source/Engine/RCCpp/RCCppUnix.h @@ -36,6 +36,7 @@ namespace Urho3D class RCCppMainObject; class RCCppObject; class RCCppCompiler; +class FileSystem; class URHO3D_API RCCppUnix : public RCCppImpl { @@ -57,6 +58,7 @@ class URHO3D_API RCCppUnix : public RCCppImpl void* library_; PCreateRCCppObject createObject_; PDestroyRCCppObject destroyObject_; + FileSystem* fileSystem_; }; } diff --git a/Source/Engine/RCCpp/RCCppWin.cpp b/Source/Engine/RCCpp/RCCppWin.cpp index ca6ed29be40..a02656248b9 100644 --- a/Source/Engine/RCCpp/RCCppWin.cpp +++ b/Source/Engine/RCCpp/RCCppWin.cpp @@ -103,6 +103,10 @@ void RCCppWin::DestroyObject(RCCppObject *object) bool RCCppWin::LoadLib(const String& libraryPath) { + if (library_ != NULL) + { + UnloadLib(); + } library_ = LoadLibrary(libraryPath.CString()); if (library_ != NULL) { @@ -124,6 +128,8 @@ void RCCppWin::UnloadLib() FreeLibrary(library_); library_ = NULL; mainObject_ = NULL; + createObject_ = NULL; + destroyObject_ = NULL; if (!oldLibPath_.Empty()) {