OverviewFilesCommitsIssuesDocsReleasesPeers

opencog-atomspace / opencog / atoms / grounded / LibraryManager.cc

108 lines · cc ref:
/*
 * opencog/atoms/execution/LibraryManager.cc
 *
 * Copyright (C) 2018 OpenCog Foundation
 * All Rights Reserved
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License v3 as
 * published by the Free Software Foundation and including the exceptions
 * at http://opencog.org/wiki/Licenses
 *
 * This program 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 Affero General Public License
 * along with this program; if not, write to:
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include <dlfcn.h>

#include "LibraryManager.h"

using namespace opencog;

std::unordered_map<std::string, void*> LibraryManager::_librarys;
std::unordered_map<std::string, void*> LibraryManager::_functions;

void LibraryManager::setLocalFunc(std::string libName, std::string funcName, void* func)
{
	if (_librarys.count(libName) == 0) {
		_librarys[libName] = NULL;
	}
	std::string funcID = libName + "\\" + funcName;
	_functions[funcID] = func;
}

void* LibraryManager::getFunc(std::string libName, std::string funcName)
{
	void* libHandle;
	if (_librarys.count(libName) == 0) {
		// Try and load the library and function.
		libHandle = dlopen(libName.c_str(), RTLD_LAZY);
		if (nullptr == libHandle)
			throw RuntimeException(TRACE_INFO,
			                       "Cannot open library: %s - %s", libName.c_str(), dlerror());
		_librarys[libName] = libHandle;
	}
	else {
		libHandle = _librarys[libName];
	}

	std::string funcID = libName + "\\" + funcName;

	void* sym;
	if (_functions.count(funcID) == 0){
		sym = dlsym(libHandle, funcName.c_str());
		if (nullptr == sym)
			throw RuntimeException(TRACE_INFO,
			                       "Cannot find symbol %s in library: %s - %s",
			                       funcName.c_str(), libName.c_str(), dlerror());
		_functions[funcID] = sym;
	}
	else {
		sym = _functions[funcID];
	}

	return sym;
}

void LibraryManager::parse_schema(const std::string& schema,
                                  std::string& lang,
                                  std::string& lib,
                                  std::string& fun)
{
	std::string::size_type pos = schema.find(":");
	if (pos == std::string::npos)
		return;

	lang = schema.substr(0, pos);

	// Move past the colon and strip leading white-space
	do { pos++; } while (' ' == schema[pos]);

	if (lang == "lib") {
		// Get the name of the Library and Function. They should be
		// separated by '\'. If no library the separator may be omitted.
		std::size_t seppos = schema.find("\\");
		if (seppos == std::string::npos) { // No library
			lib = "";
			fun = schema.substr(pos);
		} else {                  // Possible library
			lib = schema.substr(pos, seppos - pos);
			fun = schema.substr(seppos + 1);
		}
	} else
		fun = schema.substr(pos);
}

void opencog::setLocalSchema(std::string funcName,
                             ValuePtr* (*func)(AtomSpace *, Handle*))
{
	LibraryManager::setLocalFunc("", funcName, reinterpret_cast<void*>(func));
}