Calling C++ member function from Luabind causes “N

2019-04-03 02:34发布

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 ?

标签: c++ lua luabind
1条回答
祖国的老花朵
2楼-- · 2019-04-03 02:41

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
查看更多
登录 后发表回答