I've got some classes exported to Luabind in a DLL, and everything is working fine for those 2 classes (LuaScriptManager, EventManager).
I can call their functions from Lua and all is well, but now I'm trying to setup some new class in my client executable which links with the DLL and so far no luck at all.
Here's the error message I get for every function that I call:
"No matching overload found, candidates: void loadResource(ResourceManager&, std::string const&)"
The class binding is from http://www.nuclex.org/articles/5-cxx/1-quick-introduction-to-luabind:
struct Manager {
Manager() :
m_ResourceCount(0) {}
void loadResource(const std::string &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", &Manager::loadResource)
.property("ResourceCount", &Manager::getResourceCount)
];
luabind::globals(l)["MyResourceManager"] = &MyResourceManager;
}
And here's the corresponding lua test code:
-- 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)
What could be the cause of this strange behavior ?
This is a copy of a mail I sent to the Luabind mailing list.
http://sourceforge.net/mailarchive/message.php?msg_id=27420879
I am not sure if this applies to Windows and DLLs, too, but I had a similar
experience with GCC and shared modules on Linux: classes registered
with Luabind where only valid within that shared library, but caused
segmentation faults if used across shared library boundaries.
The solution was to patch the luabind::type_id class, and compare
using typeid(T).name() instead of typeid(T)::operator=. For GCC, the
reason why the typeid operator might not work across shared libraries
is explained here [1]. In this particular case, I loaded the shared
library with Lua's require(), which, unfortunately, does not pass
RTLD_GLOBAL to dlopen.
[1] http://gcc.gnu.org/faq.html#dso
The typeid equality problem has appeared in other C++ libraries, e.g.
in boost::any [2], with the same fix [3], typeid(T).name() comparison.
[2] https://svn.boost.org/trac/boost/ticket/754
[3] https://svn.boost.org/trac/boost/changeset/56168
Maybe the attached patch helps in the case of DLLs, too.
--- 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 const& other) const
{
- return *id != *other.id;
+ return std::strcmp(id->name(), other.id->name()) != 0;
}
bool operator==(type_id const& other) const
{
- return *id == *other.id;
+ return std::strcmp(id->name(), other.id->name()) == 0;
}
bool operator<(type_id const& other) const
{
- return id->before(*other.id);
+ return std::strcmp(id->name(), other.id->name()) < 0;
}
char const* name() const