loader: Add documentation

This commit is contained in:
Paweł Bylica 2018-07-05 14:16:54 +02:00
parent 49e26b1ede
commit 4a929e248a
No known key found for this signature in database
GPG Key ID: 7A0C037434FE77EF
2 changed files with 45 additions and 0 deletions

View File

@ -9,6 +9,7 @@
extern "C" {
#endif
/** Error codes for the EVMC loader. */
enum evmc_loader_error_code
{
EVMC_LOADER_SUCCESS = 0,
@ -17,6 +18,43 @@ enum evmc_loader_error_code
EVMC_LOADER_INVALID_ARGUMENT,
};
/**
* Dynamically loads the shared object (DLL) with an EVM implementation.
*
* This function tries to open a DLL at the given `filename`. On UNIX-like systems dlopen() function
* is used. On Windows LoadLibrary() function is used.
*
* If the file does not exist or is not a valid shared library the ::EVMC_ERRC_CANNOT_OPEN error
* code is signaled and NULL is returned.
*
* After the DLL is successfully loaded the function tries to find the EVM create function in the
* library. The `filename` is used to guess the EVM name and the name of the create function.
* The create function name is constructed by the following rules. Consider example path:
* "/ethereum/libexample-interpreter.so".
* - the filename is taken from the path:
* "libexample-interpreter.so",
* - the "lib" prefix and file extension are stripped from the name:
* "example-interpreter"
* - all "-" are replaced with "_" to construct _full name_:
* "example_interpreter",
* - the _full name_ is split by "_" char and the last item is taken to form the _short name_:
* "interpreter",
* - the name "evmc_create_" + _full name_ is checked in the library:
* "evmc_create_example_interpreter",
* - the name "evmc_create_" + _short name_ is checked in the library:
* "evmc_create_interpreter".
*
* If the create function is found in the library, the EVM instance is create and returned.
* Otherwise, the ::EVMC_ERRC_SYMBOL_NOT_FOUND error code is signaled and NULL is returned.
*
* @param filename The null terminated path (absolute or relative) to the shared library
* containing the EVM implementation. If the value is NULL, an empty C-string
* or longer than the path maximum length the ::EVMC_ERRC_INVALID_ARGUMENT is
* signaled.
* @param error_code The pointer to the error code. If not NULL the value is set to
* ::EVMC_ERRC_SUCCESS on success or any other error code as described above.
* @return The pointer to EVM instance if loaded successfully or NULL.
*/
struct evmc_instance* evmc_load(const char* filename, enum evmc_loader_error_code* error_code);
#if __cplusplus

View File

@ -64,14 +64,17 @@ struct evmc_instance* evmc_load(const char* filename, enum evmc_loader_error_cod
goto exit;
}
// Create name buffer with the prefix.
const char prefix[] = "evmc_create_";
const size_t prefix_length = strlen(prefix);
char name[sizeof(prefix) + PATH_MAX_LENGTH];
strcpy_s(name, sizeof(name), prefix);
// Find filename in the path.
const char* sep_pos = strrchr(filename, '/');
const char* name_pos = sep_pos ? sep_pos + 1 : filename;
// Skip "lib" prefix if present.
const char lib_prefix[] = "lib";
const size_t lib_prefix_length = strlen(lib_prefix);
if (strncmp(name_pos, lib_prefix, lib_prefix_length) == 0)
@ -79,17 +82,21 @@ struct evmc_instance* evmc_load(const char* filename, enum evmc_loader_error_cod
strcpy_s(name + prefix_length, PATH_MAX_LENGTH, name_pos);
// Trim the file extension.
char* ext_pos = strrchr(name, '.');
if (ext_pos)
*ext_pos = 0;
// Replace all "-" with "_".
char* dash_pos = name;
while ((dash_pos = strchr(dash_pos, '-')) != NULL)
*dash_pos++ = '_';
// Search for the "full name" based function name.
evmc_create_fn create_fn = DLL_GET_CREATE_FN(handle, name);
if (!create_fn)
{
// Try the "short name" based function name.
const char* short_name_pos = strrchr(name, '_');
if (short_name_pos)
{