in c/driver_manager/adbc_driver_manager.cc [634:766]
AdbcStatusCode AdbcLoadDriver(const char* driver_name, const char* entrypoint,
int version, void* raw_driver, struct AdbcError* error) {
AdbcDriverInitFunc init_func;
std::string error_message;
if (version != ADBC_VERSION_1_0_0) {
SetError(error, "Only ADBC 1.0.0 is supported");
return ADBC_STATUS_NOT_IMPLEMENTED;
}
auto* driver = reinterpret_cast<struct AdbcDriver*>(raw_driver);
if (!entrypoint) {
// Default entrypoint (see adbc.h)
entrypoint = "AdbcDriverInit";
}
#if defined(_WIN32)
HMODULE handle = LoadLibraryExA(driver_name, NULL, 0);
if (!handle) {
error_message += driver_name;
error_message += ": LoadLibraryExA() failed: ";
GetWinError(&error_message);
std::string full_driver_name = driver_name;
full_driver_name += ".lib";
handle = LoadLibraryExA(full_driver_name.c_str(), NULL, 0);
if (!handle) {
error_message += '\n';
error_message += full_driver_name;
error_message += ": LoadLibraryExA() failed: ";
GetWinError(&error_message);
}
}
if (!handle) {
SetError(error, error_message);
return ADBC_STATUS_INTERNAL;
}
void* load_handle = reinterpret_cast<void*>(GetProcAddress(handle, entrypoint));
init_func = reinterpret_cast<AdbcDriverInitFunc>(load_handle);
if (!init_func) {
std::string message = "GetProcAddress(";
message += entrypoint;
message += ") failed: ";
GetWinError(&message);
if (!FreeLibrary(handle)) {
message += "\nFreeLibrary() failed: ";
GetWinError(&message);
}
SetError(error, message);
return ADBC_STATUS_INTERNAL;
}
#else
#if defined(__APPLE__)
static const std::string kPlatformLibraryPrefix = "lib";
static const std::string kPlatformLibrarySuffix = ".dylib";
#else
static const std::string kPlatformLibraryPrefix = "lib";
static const std::string kPlatformLibrarySuffix = ".so";
#endif // defined(__APPLE__)
void* handle = dlopen(driver_name, RTLD_NOW | RTLD_LOCAL);
if (!handle) {
error_message = "dlopen() failed: ";
error_message += dlerror();
// If applicable, append the shared library prefix/extension and
// try again (this way you don't have to hardcode driver names by
// platform in the application)
const std::string driver_str = driver_name;
std::string full_driver_name;
if (driver_str.size() < kPlatformLibraryPrefix.size() ||
driver_str.compare(0, kPlatformLibraryPrefix.size(), kPlatformLibraryPrefix) !=
0) {
full_driver_name += kPlatformLibraryPrefix;
}
full_driver_name += driver_name;
if (driver_str.size() < kPlatformLibrarySuffix.size() ||
driver_str.compare(full_driver_name.size() - kPlatformLibrarySuffix.size(),
kPlatformLibrarySuffix.size(), kPlatformLibrarySuffix) != 0) {
full_driver_name += kPlatformLibrarySuffix;
}
handle = dlopen(full_driver_name.c_str(), RTLD_NOW | RTLD_LOCAL);
if (!handle) {
error_message += "\ndlopen() failed: ";
error_message += dlerror();
}
}
if (!handle) {
SetError(error, error_message);
// AdbcDatabaseInit tries to call this if set
driver->release = nullptr;
return ADBC_STATUS_INTERNAL;
}
void* load_handle = dlsym(handle, entrypoint);
if (!load_handle) {
std::string message = "dlsym(";
message += entrypoint;
message += ") failed: ";
message += dlerror();
SetError(error, message);
return ADBC_STATUS_INTERNAL;
}
init_func = reinterpret_cast<AdbcDriverInitFunc>(load_handle);
#endif // defined(_WIN32)
AdbcStatusCode status = AdbcLoadDriverFromInitFunc(init_func, version, driver, error);
if (status == ADBC_STATUS_OK) {
ManagerDriverState* state = new ManagerDriverState;
state->driver_release = driver->release;
#if defined(_WIN32)
state->handle = handle;
#endif // defined(_WIN32)
driver->release = &ReleaseDriver;
driver->private_manager = state;
} else {
#if defined(_WIN32)
if (!FreeLibrary(handle)) {
std::string message = "FreeLibrary() failed: ";
GetWinError(&message);
SetError(error, message);
}
#endif // defined(_WIN32)
}
return status;
}