#c #lua #luabind
#c #lua #luabind
Вопрос:
У меня есть несколько классов, экспортированных в Luabind в DLL, и все работает нормально для этих двух классов (LuaScriptManager, EventManager). Я могу вызывать их функции из Lua, и все хорошо, но сейчас я пытаюсь настроить какой-то новый класс в моем клиентском исполняемом файле, который связывается с DLL, и пока что совсем безуспешно.
Вот сообщение об ошибке, которое я получаю для каждой функции, которую я вызываю: «Перегрузка соответствия не найдена, кандидаты: void LoadResource(ResourceManageramp;, std::string constamp;)»
Привязка к классу выполняется из http://www.nuclex.org/articles/5-cxx/1-quick-introduction-to-luabind:
struct Manager {
Manager() :
m_ResourceCount(0) {}
void loadResource(const std::string amp;sFilename) {
m_ResourceCount;
}
size_t getResourceCount() const {
return m_ResourceCount;
}
size_t m_ResourceCount;
};
static Manager MyResourceManager;
void Bind(lua_State* l)
{
// Export our class with LuaBind
luabind::module(l) [
luabind::class_<Manager>("ResourceManager")
.def("loadResource", amp;Manager::loadResource)
.property("ResourceCount", amp;Manager::getResourceCount)
];
luabind::globals(l)["MyResourceManager"] = amp;MyResourceManager;
}
И вот соответствующий тестовый код lua:
-- The following call will fail with the above error
MyResourceManager:loadResource("abc.res")
--MyResourceManager:loadResource("xyz.res")
-- If the function is commented out, this will work (accessing the property)
ResourceCount = MyResourceManager.ResourceCount
-- Calling my other classes' functions work fine
LuaScriptManager.GetInstance():WriteLine(ResourceCount)
Что может быть причиной такого странного поведения?
Комментарии:
1. Хорошо, я сузил область поиска до: если состояние lua открыто в DLL = не работает, если состояние lua открыто в клиентском exe = работает. Но, конечно, я хотел бы иметь одинаковое состояние в обоих, чтобы я мог совместно использовать объекты между ними….
2. Может ли это быть проблемой с искажением имени?
Ответ №1:
Это копия письма, которое я отправил в список рассылки Luabind. http://sourceforge.net/mailarchive/message.php?msg_id=27420879
Я не уверен, относится ли это также к Windows и библиотекам DLL, но у меня был аналогичный опыт с GCC и общими модулями в Linux: классы, зарегистрированные в Luabind, были действительны только в этой общей библиотеке, но вызывали ошибки сегментации, если использовались за пределами границ общей библиотеки.
Решением было исправить класс luabind::type_id и сравнить, используя typeid(T).name() вместо typeid(T)::operator= . Для GCC причина, по которой оператор typeid может не работать в совместно используемых библиотеках, объясняется здесь [1]. В данном конкретном случае я загрузил разделяемую библиотеку с помощью функции require() Lua, которая, к сожалению, не передает RTLD_GLOBAL в dlopen.
[1] http://gcc.gnu.org/faq.html#dso
Проблема равенства typeid появилась в других библиотеках C , например
в boost::any [2], с тем же исправлением [3], сравнение typeid(T).name().
[2] https://svn.boost.org/trac/boost/ticket/754
[3] https://svn.boost.org/trac/boost/changeset/56168
Возможно, прилагаемый патч помогает и в случае DLL-файлов.
--- include.orig/luabind/typeid.hpp
include/luabind/typeid.hpp
@@ -6,6 6,7 @@
# define LUABIND_TYPEID_081227_HPP
# include <boost/operators.hpp>
# include <cstring>
# include <typeinfo>
# include <luabind/detail/primitives.hpp>
@@ -33,17 34,17 @@
bool operator!=(type_id constamp; other) const
{
- return *id != *other.id;
return std::strcmp(id->name(), other.id->name()) != 0;
}
bool operator==(type_id constamp; other) const
{
- return *id == *other.id;
return std::strcmp(id->name(), other.id->name()) == 0;
}
bool operator<(type_id constamp; other) const
{
- return id->before(*other.id);
return std::strcmp(id->name(), other.id->name()) < 0;
}
char const* name() const