aboutsummaryrefslogtreecommitdiff
path: root/src/main.cpp
blob: 6deb43645ac507895b92b3e0531e20c3069465ff (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/* 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 <http://www.gnu.org/licenses/>.
 *
 * To contact Galois, complete the Web form at <http://corp.galois.com/contact/>
 * or write to Galois, Inc., 421 Southwest 6th Avenue, Suite 300, Portland,
 * Oregon, 97204-1622. */

#ifdef HAVE_CONFIG_H
#   include <config.h>
#endif

#include <cstddef>

#include <exception>
#include <stdexcept>
#include <string>

#include <boost/filesystem.hpp>
#include <v_repLib.h>

#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)) {
    }

}