#ifndef EXTERNALCODE_H_INCLUDED_ #define EXTERNALCODE_H_INCLUDED_ #include "globalincs/pstypes.h" /* This class loads external libraries for FSO use. * Uses SDL to do the actual loading so this should be supported on most platforms */ class SCP_ExternalCode { public: SCP_ExternalCode( ) : m_library(NULL) { } virtual ~SCP_ExternalCode() { if (m_library) SDL_UnloadObject(m_library); } protected: bool LoadExternal( const char* externlib, const char* basePath = nullptr ) { if ( !externlib ) return FALSE; m_library = SDL_LoadObject(externlib); #ifdef __ANDROID__ if (m_library == NULL) { auto android_path = SDL_GetAndroidInternalStoragePath(); if (android_path != nullptr) { SCP_string android_full_path = android_path; if (android_full_path.back() != DIR_SEPARATOR_CHAR) { android_full_path += DIR_SEPARATOR_CHAR; } android_full_path += SCP_string("natives") + DIR_SEPARATOR_CHAR + externlib; #ifndef NDEBUG mprintf(("Calling SDL_LoadObject with the following path: '%s'\n", android_full_path.c_str())); #endif m_library = SDL_LoadObject(android_full_path.c_str()); } } #endif // check full path as a fallback for our own libraries // NOTE: basePath is assumed to have a trailing slash! if ( !m_library && basePath ) { SCP_string fullpath = basePath; fullpath += externlib; m_library = SDL_LoadObject(fullpath.c_str()); } #ifndef NDEBUG if (m_library == NULL) { mprintf(("Failed to load library '%s': '%s'\n", externlib, SDL_GetError())); } #endif return m_library != NULL; } void* LoadFunction(const char* functionname) { if (m_library != NULL && functionname != NULL) { void* func = reinterpret_cast(SDL_LoadFunction(m_library, functionname)); #ifndef NDEBUG if (func == NULL) { mprintf(("Failed to load function '%s': '%s'\n", functionname, SDL_GetError())); } #endif return func; } return NULL; } template FuncType LoadFunction(const char* functionname) { return reinterpret_cast(LoadFunction(functionname)); } private: SDL_SharedObject* m_library; }; /* These are available if you're compiling an external DLL * So far we have trackir, and speech is on the way */ #ifdef _WIN32 # define SCP_EXT_CALLCONV __cdecl # ifdef SCPDLL_EXTERNAL_LIB # define SCPDLL_EXTERNAL __declspec( dllexport ) # else # define SCPDLL_EXTERNAL __declspec( dllimport ) # endif /* Must be in a CPP file in your DLL code * If you want to write your own, you shouldn't. */ # define SCPDLL_DLLMAIN( ) \ SCP_EXTERN_C BOOL APIENTRY DllMain( HANDLE, DWORD, LPVOID ) { return TRUE; } #else # define SCP_EXT_CALLCONV # define SCPDLL_EXTERNAL # define SCPDLL_DLLMAIN( ) #endif #ifdef __cplusplus # define SCP_EXTERN_C extern "C" #else # define SCP_EXTERN_C #endif /* Version information */ typedef struct _SCPDLL_Version { int major; int minor; int patch; } SCPDLL_Version; typedef int (SCP_EXT_CALLCONV *SCPDLL_PFVERSION)(SCPDLL_Version*); /* Must be in a CPP file in your DLL code */ #define SCPDLL_VERSION_FUNCTION( Major, Minor, Patch ) \ SCP_EXTERN_C int SCPDLL_EXTERNAL SCPDLL_GetVersion( SCPDLL_Version* v ) { \ if ( !v ) return -1;\ v->major = Major; v->minor = Minor; v->patch = Patch;\ return 0; } #endif /* EXTERNALCODE_H_INCLUDED_ */