Skip to content

Commit

Permalink
Update the sdk bootstrap code to fail fast on clear problems with the…
Browse files Browse the repository at this point in the history
… lib from alfasim

The problems covered in this update:

- Can not load the lib (not found or corrupted);
- Can not fetch the address of a function from the lib;

ASIM-5532
  • Loading branch information
prusse-martin committed Jun 14, 2024
1 parent 1214f36 commit dbf8d65
Show file tree
Hide file tree
Showing 3 changed files with 136 additions and 92 deletions.
2 changes: 2 additions & 0 deletions src/alfasim_sdk/alfasim_sdk_api/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ struct VariableScope
It holds the possible returning error code when trying to open ALFAsim-SDK API.
*/
enum sdk_load_error_code {
SDK_FAILED_TO_LOAD_FUNCTION=-4, /*!< Some function from SDK dll could not be loaded.*/
SDK_FAILED_TO_LOAD_DLL=-3, /*!< SDK dll could not be loaded.*/
SDK_DLL_PATH_TOO_LONG=-2, /*!< Path to SDK dll too long (Windows limitation).*/
SDK_ALREADY_OPEN_ERROR=-1, /*!< SDK dll already Opened.*/
SDK_OK=0 /*!< Everything was fine.*/
Expand Down
116 changes: 70 additions & 46 deletions src/alfasim_sdk/alfasim_sdk_api/detail/bootstrap_linux.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,56 +44,80 @@ inline int alfasim_sdk_open(ALFAsimSDK_API* api)
// Load shared object
char *full_filepath = NULL;
asprintf(&full_filepath, "%s%s", alfasim_executable_dir, SO_FILENAME);

// https://www.man7.org/linux/man-pages/man3/dlopen.3.html
// > If dlopen() fails for any reason, it returns NULL.
api->handle = dlopen(full_filepath, RTLD_LAZY);
free(full_filepath);
if (api->handle == NULL) {
return SDK_FAILED_TO_LOAD_DLL;
}

// https://man7.org/linux/man-pages/man3/dlsym.3.html
// > In unusual cases (see NOTES) the value of the symbol could actually be NULL. Therefore,
// > a NULL return from dlsym() need not indicate an error. The correct way to distinguish an
// > error from a symbol whose value is NULL is to call dlerror(3) to clear any old error
// > conditions, then call dlsym(), and then call dlerror(3) again, saving its return value
// > into a variable, and check whether this saved value is not NULL.
#define LOAD_SDK_PROC_MAP_TYPE(func_name, func_type) {\
dlerror();\
api->func_name = (func_type)dlsym(api->handle, #func_name);\
char *last_error = dlerror();\
if (last_error != NULL) {\
dlclose(api->handle);\
api->handle = nullptr;\
return SDK_FAILED_TO_LOAD_FUNCTION;\
}\
}
#define LOAD_SDK_PROC(func_name) LOAD_SDK_PROC_MAP_TYPE(func_name, func_name ## _func)

// Register alfasim API
api->set_plugin_data = (set_plugin_data_func)dlsym(api->handle, "set_plugin_data");
api->get_plugin_data = (get_plugin_data_func)dlsym(api->handle, "get_plugin_data");
api->get_number_of_threads = (get_number_of_threads_func)dlsym(api->handle, "get_number_of_threads");
api->get_thread_id = (get_thread_id_func)dlsym(api->handle, "get_thread_id");
api->get_plugin_input_data_boolean = (get_plugin_input_data_boolean_func)dlsym(api->handle, "get_plugin_input_data_boolean");
api->get_plugin_input_data_enum = (get_plugin_input_data_enum_func)dlsym(api->handle, "get_plugin_input_data_enum");
api->get_plugin_input_data_quantity = (get_plugin_input_data_quantity_func)dlsym(api->handle, "get_plugin_input_data_quantity");
api->get_plugin_input_data_string = (get_plugin_input_data_string_func)dlsym(api->handle, "get_plugin_input_data_string");
api->get_plugin_input_data_string_size = (get_plugin_input_data_string_size_func)dlsym(api->handle, "get_plugin_input_data_string_size");
api->get_plugin_input_data_file_content = (get_plugin_input_data_file_content_func)dlsym(api->handle, "get_plugin_input_data_file_content");
api->get_plugin_input_data_file_content_size = (get_plugin_input_data_file_content_size_func)dlsym(api->handle, "get_plugin_input_data_file_content_size");
api->get_plugin_input_data_reference = (get_plugin_input_data_reference_func)dlsym(api->handle, "get_plugin_input_data_reference");
api->get_plugin_variable = (get_plugin_variable_func)dlsym(api->handle, "get_plugin_variable");
api->get_field_id = (get_field_id_func)dlsym(api->handle, "get_field_id");
api->get_phase_id = (get_phase_id_func)dlsym(api->handle, "get_phase_id");
api->get_layer_id = (get_layer_id_func)dlsym(api->handle, "get_layer_id");
api->get_number_of_fields = (get_number_of_fields_func)dlsym(api->handle, "get_number_of_fields");
api->get_number_of_phases = (get_number_of_phases_func)dlsym(api->handle, "get_number_of_phases");
api->get_number_of_layers = (get_number_of_layers_func)dlsym(api->handle, "get_number_of_layers");
api->get_number_of_phase_pairs = (get_number_of_phase_pairs_func)dlsym(api->handle, "get_number_of_phase_pairs");
api->get_primary_field_id_of_phase = (get_field_id_func)dlsym(api->handle, "get_primary_field_id_of_phase");
api->get_phase_id_of_fields = (get_phase_id_of_fields_func)dlsym(api->handle, "get_phase_id_of_fields");
api->get_field_ids_in_layer = (get_field_ids_in_layer_func)dlsym(api->handle, "get_field_ids_in_layer");
api->get_phase_pair_id = (get_phase_pair_id_func)dlsym(api->handle, "get_phase_pair_id");
api->get_state_variable_array = (get_state_variable_array_func)dlsym(api->handle, "get_state_variable_array");
api->get_simulation_array = (get_simulation_array_func)dlsym(api->handle, "get_simulation_array");
api->get_simulation_tracer_array = (get_simulation_tracer_array_func)dlsym(api->handle, "get_simulation_tracer_array");
api->get_simulation_quantity = (get_simulation_quantity_func)dlsym(api->handle, "get_simulation_quantity");
api->get_wall_interfaces_temperature = (get_wall_interfaces_temperature_func)dlsym(api->handle, "get_wall_interfaces_temperature");
api->get_flow_pattern = (get_flow_pattern_func)dlsym(api->handle, "get_flow_pattern");
api->get_liqliq_flow_pattern = (get_flow_pattern_func)dlsym(api->handle, "get_liqliq_flow_pattern");
api->get_deposition_thickness = (get_deposition_thickness_func)dlsym(api->handle, "get_deposition_thickness");
api->get_plugin_input_data_table_quantity = (get_plugin_input_data_table_quantity_func)dlsym(api->handle, "get_plugin_input_data_table_quantity");
api->get_tracer_id = (get_tracer_id_func)dlsym(api->handle, "get_tracer_id");
api->get_tracer_name_size = (get_tracer_name_size_func)dlsym(api->handle, "get_tracer_name_size");
api->get_tracer_name = (get_tracer_name_func)dlsym(api->handle, "get_tracer_name");
api->get_tracer_ref_by_name = (get_tracer_ref_by_name_func)dlsym(api->handle, "get_tracer_ref_by_name");
api->get_tracer_partition_coefficient = (get_tracer_partition_coefficient_func)dlsym(api->handle, "get_tracer_partition_coefficient");
api->get_plugin_input_data_multiplereference_selected_size = (get_plugin_input_data_multiplereference_selected_size_func)dlsym(api->handle, "get_plugin_input_data_multiplereference_selected_size");
api->get_ucm_friction_factor_input_variable = (get_input_variable_func)dlsym(api->handle, "get_ucm_friction_factor_input_variable");
api->get_ucm_fluid_geometrical_properties = (get_ucm_fluid_geometrical_properties_func)dlsym(api->handle, "get_ucm_fluid_geometrical_properties");
api->get_liq_liq_flow_pattern_input_variable = (get_input_variable_func)dlsym(api->handle, "get_liq_liq_flow_pattern_input_variable");
api->get_liquid_effective_viscosity_input_variable = (get_input_variable_func)dlsym(api->handle, "get_liquid_effective_viscosity_input_variable");
api->get_gas_liq_surface_tension_input_variable = (get_input_variable_func)dlsym(api->handle, "get_gas_liq_surface_tension_input_variable");
api->get_liq_liq_shear_force_per_volume_input_variable = (get_input_variable_func)dlsym(api->handle, "get_liq_liq_shear_force_per_volume_input_variable");
api->get_relative_emulsion_viscosity = (get_relative_emulsion_viscosity_func)dlsym(api->handle, "get_relative_emulsion_viscosity");
LOAD_SDK_PROC(set_plugin_data)
LOAD_SDK_PROC(get_plugin_data)
LOAD_SDK_PROC(get_number_of_threads)
LOAD_SDK_PROC(get_thread_id)
LOAD_SDK_PROC(get_plugin_input_data_boolean)
LOAD_SDK_PROC(get_plugin_input_data_enum)
LOAD_SDK_PROC(get_plugin_input_data_quantity)
LOAD_SDK_PROC(get_plugin_input_data_string)
LOAD_SDK_PROC(get_plugin_input_data_string_size)
LOAD_SDK_PROC(get_plugin_input_data_file_content)
LOAD_SDK_PROC(get_plugin_input_data_file_content_size)
LOAD_SDK_PROC(get_plugin_input_data_reference)
LOAD_SDK_PROC(get_plugin_variable)
LOAD_SDK_PROC(get_field_id)
LOAD_SDK_PROC(get_phase_id)
LOAD_SDK_PROC(get_layer_id)
LOAD_SDK_PROC(get_number_of_fields)
LOAD_SDK_PROC(get_number_of_phases)
LOAD_SDK_PROC(get_number_of_layers)
LOAD_SDK_PROC(get_number_of_phase_pairs)
LOAD_SDK_PROC_MAP_TYPE(get_primary_field_id_of_phase, get_field_id_func)
LOAD_SDK_PROC(get_phase_id_of_fields)
LOAD_SDK_PROC(get_field_ids_in_layer)
LOAD_SDK_PROC(get_phase_pair_id)
LOAD_SDK_PROC(get_state_variable_array)
LOAD_SDK_PROC(get_simulation_array)
LOAD_SDK_PROC(get_simulation_tracer_array)
LOAD_SDK_PROC(get_simulation_quantity)
LOAD_SDK_PROC(get_wall_interfaces_temperature)
LOAD_SDK_PROC(get_flow_pattern)
LOAD_SDK_PROC_MAP_TYPE(get_liqliq_flow_pattern, get_flow_pattern_func)
LOAD_SDK_PROC(get_deposition_thickness)
LOAD_SDK_PROC(get_plugin_input_data_table_quantity)
LOAD_SDK_PROC(get_tracer_id)
LOAD_SDK_PROC(get_tracer_name_size)
LOAD_SDK_PROC(get_tracer_name)
LOAD_SDK_PROC(get_tracer_ref_by_name)
LOAD_SDK_PROC(get_tracer_partition_coefficient)
LOAD_SDK_PROC(get_plugin_input_data_multiplereference_selected_size)
LOAD_SDK_PROC_MAP_TYPE(get_ucm_friction_factor_input_variable, get_input_variable_func)
LOAD_SDK_PROC(get_ucm_fluid_geometrical_properties)
LOAD_SDK_PROC_MAP_TYPE(get_liq_liq_flow_pattern_input_variable, get_input_variable_func)
LOAD_SDK_PROC_MAP_TYPE(get_liquid_effective_viscosity_input_variable, get_input_variable_func)
LOAD_SDK_PROC_MAP_TYPE(get_gas_liq_surface_tension_input_variable, get_input_variable_func)
LOAD_SDK_PROC_MAP_TYPE(get_liq_liq_shear_force_per_volume_input_variable, get_input_variable_func)
LOAD_SDK_PROC(get_relative_emulsion_viscosity)

return SDK_OK;
}
Expand Down
110 changes: 64 additions & 46 deletions src/alfasim_sdk/alfasim_sdk_api/detail/bootstrap_win.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,56 +68,74 @@ inline int alfasim_sdk_open(ALFAsimSDK_API* api)
full_filepath[0] = '\0';
StringCchCatW(full_filepath, MAX_PATH_SIZE, alfasim_executable_dir);
StringCchCatW(full_filepath, MAX_PATH_SIZE, DLL_FILENAME);

// https://learn.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryw
// > If the function fails, the return value is NULL.
api->handle = LoadLibraryW(full_filepath);
free(executable_dir_from_env);
if (api->handle == NULL) {
return SDK_FAILED_TO_LOAD_DLL;
}

// https://learn.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getprocaddress
// > If the function fails, the return value is NULL.
#define LOAD_SDK_PROC_MAP_TYPE(func_name, func_type) {\
api->func_name = (func_type)GetProcAddress(api->handle, #func_name);\
if (api->func_name == NULL) {\
FreeLibrary(api->handle);\
api->handle = nullptr;\
return SDK_FAILED_TO_LOAD_FUNCTION;\
}\
}
#define LOAD_SDK_PROC(func_name) LOAD_SDK_PROC_MAP_TYPE(func_name, func_name ## _func)

// Register alfasim API
api->set_plugin_data = (set_plugin_data_func)GetProcAddress(api->handle, "set_plugin_data");
api->get_plugin_data = (get_plugin_data_func)GetProcAddress(api->handle, "get_plugin_data");
api->get_number_of_threads = (get_number_of_threads_func)GetProcAddress(api->handle, "get_number_of_threads");
api->get_thread_id = (get_thread_id_func)GetProcAddress(api->handle, "get_thread_id");
api->get_plugin_input_data_boolean = (get_plugin_input_data_boolean_func)GetProcAddress(api->handle, "get_plugin_input_data_boolean");
api->get_plugin_input_data_enum = (get_plugin_input_data_enum_func)GetProcAddress(api->handle, "get_plugin_input_data_enum");
api->get_plugin_input_data_quantity = (get_plugin_input_data_quantity_func)GetProcAddress(api->handle, "get_plugin_input_data_quantity");
api->get_plugin_input_data_string = (get_plugin_input_data_string_func)GetProcAddress(api->handle, "get_plugin_input_data_string");
api->get_plugin_input_data_string_size = (get_plugin_input_data_string_size_func)GetProcAddress(api->handle, "get_plugin_input_data_string_size");
api->get_plugin_input_data_file_content = (get_plugin_input_data_file_content_func)GetProcAddress(api->handle, "get_plugin_input_data_file_content");
api->get_plugin_input_data_file_content_size = (get_plugin_input_data_file_content_size_func)GetProcAddress(api->handle, "get_plugin_input_data_file_content_size");
api->get_plugin_input_data_reference = (get_plugin_input_data_reference_func)GetProcAddress(api->handle, "get_plugin_input_data_reference");
api->get_plugin_variable = (get_plugin_variable_func)GetProcAddress(api->handle, "get_plugin_variable");
api->get_field_id = (get_field_id_func)GetProcAddress(api->handle, "get_field_id");
api->get_phase_id = (get_phase_id_func)GetProcAddress(api->handle, "get_phase_id");
api->get_layer_id = (get_layer_id_func)GetProcAddress(api->handle, "get_layer_id");
api->get_number_of_fields = (get_number_of_fields_func)GetProcAddress(api->handle, "get_number_of_fields");
api->get_number_of_phases = (get_number_of_phases_func)GetProcAddress(api->handle, "get_number_of_phases");
api->get_number_of_layers = (get_number_of_layers_func)GetProcAddress(api->handle, "get_number_of_layers");
api->get_number_of_phase_pairs = (get_number_of_phase_pairs_func)GetProcAddress(api->handle, "get_number_of_phase_pairs");
api->get_primary_field_id_of_phase = (get_primary_field_id_of_phase_func)GetProcAddress(api->handle, "get_primary_field_id_of_phase");
api->get_phase_id_of_fields = (get_phase_id_of_fields_func)GetProcAddress(api->handle, "get_phase_id_of_fields");
api->get_field_ids_in_layer = (get_field_ids_in_layer_func)GetProcAddress(api->handle, "get_field_ids_in_layer");
api->get_phase_pair_id = (get_phase_pair_id_func)GetProcAddress(api->handle, "get_phase_pair_id");
api->get_state_variable_array = (get_state_variable_array_func)GetProcAddress(api->handle, "get_state_variable_array");
api->get_simulation_array = (get_simulation_array_func)GetProcAddress(api->handle, "get_simulation_array");
api->get_simulation_tracer_array = (get_simulation_tracer_array_func)GetProcAddress(api->handle, "get_simulation_tracer_array");
api->get_simulation_quantity = (get_simulation_quantity_func)GetProcAddress(api->handle, "get_simulation_quantity");
api->get_wall_interfaces_temperature = (get_wall_interfaces_temperature_func)GetProcAddress(api->handle, "get_wall_interfaces_temperature");
api->get_flow_pattern = (get_flow_pattern_func)GetProcAddress(api->handle, "get_flow_pattern");
api->get_liqliq_flow_pattern = (get_flow_pattern_func)GetProcAddress(api->handle, "get_liqliq_flow_pattern");
api->get_deposition_thickness = (get_deposition_thickness_func)GetProcAddress(api->handle, "get_deposition_thickness");
api->get_plugin_input_data_table_quantity = (get_plugin_input_data_table_quantity_func)GetProcAddress(api->handle, "get_plugin_input_data_table_quantity");
api->get_tracer_id = (get_tracer_id_func)GetProcAddress(api->handle, "get_tracer_id");
api->get_tracer_name_size = (get_tracer_name_size_func)GetProcAddress(api->handle, "get_tracer_name_size");
api->get_tracer_name = (get_tracer_name_func)GetProcAddress(api->handle, "get_tracer_name");
api->get_tracer_ref_by_name = (get_tracer_ref_by_name_func)GetProcAddress(api->handle, "get_tracer_ref_by_name");
api->get_tracer_partition_coefficient = (get_tracer_partition_coefficient_func)GetProcAddress(api->handle, "get_tracer_partition_coefficient");
api->get_plugin_input_data_multiplereference_selected_size = (get_plugin_input_data_multiplereference_selected_size_func)GetProcAddress(api->handle, "get_plugin_input_data_multiplereference_selected_size");
api->get_ucm_friction_factor_input_variable = (get_input_variable_func)GetProcAddress(api->handle, "get_ucm_friction_factor_input_variable");
api->get_ucm_fluid_geometrical_properties = (get_ucm_fluid_geometrical_properties_func)GetProcAddress(api->handle, "get_ucm_fluid_geometrical_properties");
api->get_liq_liq_flow_pattern_input_variable = (get_input_variable_func)GetProcAddress(api->handle, "get_liq_liq_flow_pattern_input_variable");
api->get_liquid_effective_viscosity_input_variable = (get_input_variable_func)GetProcAddress(api->handle, "get_liquid_effective_viscosity_input_variable");
api->get_gas_liq_surface_tension_input_variable = (get_input_variable_func)GetProcAddress(api->handle, "get_gas_liq_surface_tension_input_variable");
api->get_liq_liq_shear_force_per_volume_input_variable = (get_input_variable_func)GetProcAddress(api->handle, "get_liq_liq_shear_force_per_volume_input_variable");
api->get_relative_emulsion_viscosity = (get_relative_emulsion_viscosity_func)GetProcAddress(api->handle, "get_relative_emulsion_viscosity");
LOAD_SDK_PROC(set_plugin_data)
LOAD_SDK_PROC(get_plugin_data)
LOAD_SDK_PROC(get_number_of_threads)
LOAD_SDK_PROC(get_thread_id)
LOAD_SDK_PROC(get_plugin_input_data_boolean)
LOAD_SDK_PROC(get_plugin_input_data_enum)
LOAD_SDK_PROC(get_plugin_input_data_quantity)
LOAD_SDK_PROC(get_plugin_input_data_string)
LOAD_SDK_PROC(get_plugin_input_data_string_size)
LOAD_SDK_PROC(get_plugin_input_data_file_content)
LOAD_SDK_PROC(get_plugin_input_data_file_content_size)
LOAD_SDK_PROC(get_plugin_input_data_reference)
LOAD_SDK_PROC(get_plugin_variable)
LOAD_SDK_PROC(get_field_id)
LOAD_SDK_PROC(get_phase_id)
LOAD_SDK_PROC(get_layer_id)
LOAD_SDK_PROC(get_number_of_fields)
LOAD_SDK_PROC(get_number_of_phases)
LOAD_SDK_PROC(get_number_of_layers)
LOAD_SDK_PROC(get_number_of_phase_pairs)
LOAD_SDK_PROC(get_primary_field_id_of_phase)
LOAD_SDK_PROC(get_phase_id_of_fields)
LOAD_SDK_PROC(get_field_ids_in_layer)
LOAD_SDK_PROC(get_phase_pair_id)
LOAD_SDK_PROC(get_state_variable_array)
LOAD_SDK_PROC(get_simulation_array)
LOAD_SDK_PROC(get_simulation_tracer_array)
LOAD_SDK_PROC(get_simulation_quantity)
LOAD_SDK_PROC(get_wall_interfaces_temperature)
LOAD_SDK_PROC(get_flow_pattern)
LOAD_SDK_PROC_MAP_TYPE(get_liqliq_flow_pattern, get_flow_pattern_func)
LOAD_SDK_PROC(get_deposition_thickness)
LOAD_SDK_PROC(get_plugin_input_data_table_quantity)
LOAD_SDK_PROC(get_tracer_id)
LOAD_SDK_PROC(get_tracer_name_size)
LOAD_SDK_PROC(get_tracer_name)
LOAD_SDK_PROC(get_tracer_ref_by_name)
LOAD_SDK_PROC(get_tracer_partition_coefficient)
LOAD_SDK_PROC(get_plugin_input_data_multiplereference_selected_size)
LOAD_SDK_PROC_MAP_TYPE(get_ucm_friction_factor_input_variable, get_input_variable_func)
LOAD_SDK_PROC(get_ucm_fluid_geometrical_properties)
LOAD_SDK_PROC_MAP_TYPE(get_liq_liq_flow_pattern_input_variable, get_input_variable_func)
LOAD_SDK_PROC_MAP_TYPE(get_liquid_effective_viscosity_input_variable, get_input_variable_func)
LOAD_SDK_PROC_MAP_TYPE(get_gas_liq_surface_tension_input_variable, get_input_variable_func)
LOAD_SDK_PROC_MAP_TYPE(get_liq_liq_shear_force_per_volume_input_variable, get_input_variable_func)
LOAD_SDK_PROC(get_relative_emulsion_viscosity)

return SDK_OK;
}
Expand Down

0 comments on commit dbf8d65

Please sign in to comment.