/* main.cpp -- plugin entry points
* Copyright (C) 2013 Galois, Inc.
*
* This library is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this library. If not, see .
*
* To contact Galois, complete the Web form at
* or write to Galois, Inc., 421 Southwest 6th Avenue, Suite 300, Portland,
* Oregon, 97204-1622. */
#ifdef HAVE_CONFIG_H
# include
#endif
#include
#include
#include
#include
#include
#include
#include "automobile.h"
#include "main.h"
#include "vrep.h"
#include "vrepFfi.h"
namespace {
const unsigned char PLUGIN_VERSION = 1;
// The V-REP library that will get loaded at runtime
const std::string VREP_LIBRARY_NAME = "libv_rep.so";
LIBRARY vrepLibrary;
// Prototypes //
/* The library we think we're loading might not actually be the right
* library. */
class BadLibraryError : public std::runtime_error {
public:
explicit inline BadLibraryError();
};
// We might be using a too-old V-REP.
class TooOldVrepError : public std::runtime_error {
public:
explicit inline TooOldVrepError(const simInt version);
};
/* Loads the V-REP library and ensures it has the correct set of symbols.
* Throws 'std::exception' if an error occurs. */
// This function is declared inline because it is only used once.
inline void loadAndValidateVrepLibrary();
/* Throws 'std::exception' if the current version of V-REP is strictly less
than the 'simInt' passed. */
// This function is declared inline because it is only used once.
inline void requireVrepVersion(const simInt);
}
unsigned char v_repStart(void *, int) {
try {
loadAndValidateVrepLibrary();
// If we needed a specific version of V-REP, we'd check it here with
// 'requireVrepVersion'.
vrep::InterfaceLockGuard lockInterface;
// Register functions.
registerLuaFunctions();
// Returning zero indicates a failure condition.
static_assert(PLUGIN_VERSION != 0, "Plugin version must be nonzero");
return PLUGIN_VERSION;
} catch (const std::exception& error) {
// Loading the plugin failed. Return 0 to indicate failure.
return 0;
}
}
void v_repEnd() {
unloadVrepLibrary(vrepLibrary);
}
void *v_repMessage(int, int *, void *, int *) {
return nullptr;
}
namespace {
void loadAndValidateVrepLibrary() {
try {
// Load the V-REP library out of the V-REP directory.
const std::string vrepLibraryPath =
boost::filesystem::current_path().string()
+ "/" + VREP_LIBRARY_NAME;
vrepLibrary = loadVrepLibrary(vrepLibraryPath.c_str());
// Make sure we can actually get code out of the V-REP library.
if (getVrepProcAddresses(vrepLibrary) == 0) {
throw BadLibraryError();
}
} catch (const std::exception& e) {
// Problems occurred loading the library; unload it before leaving.
unloadVrepLibrary(vrepLibrary);
throw e;
}
}
void requireVrepVersion(const simInt expected) {
simInt actual;
VREP(simGetIntegerParameter(sim_intparam_program_version, &actual));
if (actual < expected) {
throw TooOldVrepError(expected);
}
}
BadLibraryError::BadLibraryError()
: std::runtime_error("could not find all required functions in "
+ VREP_LIBRARY_NAME) {
}
TooOldVrepError::TooOldVrepError(const simInt version)
: std::runtime_error("plugin requires V-REP >= "
+ std::to_string(version)) {
}
}