luabind: cannot retrieve values from table indexed by non-built-in classes‏ - c++

I'm using luabind 0.9.1 from Ryan Pavlik's master distribution with Lua 5.1, cygwin on Win XP SP3 + latest patches x86, boost 1.48, gcc 4.3.4. Lua and boost are cygwin pre-compiled versions.
I've successfully built luabind in both static and shared versions.
Both versions pass all the tests EXCEPT for the test_object_identity.cpp test which fails in both versions.
I've tracked down the problem to the following issue:
If an entry in a table is created for NON built-in class (i.e., not int, string, etc), the value CANNOT be retrieved.
Here's a code piece that demonstrates this:
#include "test.hpp"
#include <luabind/luabind.hpp>
#include <luabind/detail/debug.hpp>
using namespace luabind;
struct test_param
{
int obj;
};
void test_main(lua_State* L)
{
using namespace luabind;
module(L)
[
class_<test_param>("test_param")
.def_readwrite("obj", &test_param::obj)
];
test_param temp_object;
object tabc = newtable(L);
tabc[1] = 10;
tabc[temp_object] = 30;
TEST_CHECK( tabc[1] == 10 ); // passes
TEST_CHECK( tabc[temp_object] == 30 ); // FAILS!!!
}
tabc[1] is indeed 10 while tabc[temp_object] is NOT 30! (actually, it seems to be nil)
However, if I use iterate to go over tabc entries, there're the two entries with the CORRECT key/value pairs.
Any ideas?
BTW, overloading the == operator like this:
#include <luabind/operator.hpp>
struct test_param
{
int obj;
bool operator==(test_param const& rhs) const
{
return obj == rhs.obj;
}
};
and
module(L)
[
class_<test_param>("test_param")
.def_readwrite("obj", &test_param::obj)
.def(const_self == const_self)
];
Doesn't change the result.
I also tried switching to settable() and gettable() from the [] operator. The result is the same. I can see with the debugger that default conversion of the key is invoked, so I guess the error arises from somewhere therein, but it's beyond me to figure out what exactly the problem is.
As the following simple test case show, there're definitely a bug in Luabind's conversion for complex types:
struct test_param : wrap_base
{
int obj;
bool operator==(test_param const& rhs) const
{ return obj == rhs.obj ; }
};
void test_main(lua_State* L)
{
using namespace luabind;
module(L)
[
class_<test_param>("test_param")
.def(constructor<>())
.def_readwrite("obj", &test_param::obj)
.def(const_self == const_self)
];
object tabc, zzk, zzv;
test_param tp, tp1;
tp.obj = 123456;
// create new table
tabc = newtable(L);
// set tabc[tp] = 5;
// o k v
settable( tabc, tp, 5);
// get access to entry through iterator() API
iterator zzi(tabc);
// get the key object
zzk = zzi.key();
// read back the value through gettable() API
// o k
zzv = gettable(tabc, zzk);
// check the entry has the same value
// irrespective of access method
TEST_CHECK ( *zzi == 5 &&
object_cast<int>(zzv) == 5 );
// convert key to its REAL type (test_param)
tp1 = object_cast<test_param>(zzk);
// check two keys are the same
TEST_CHECK( tp == tp1 );
// read the value back from table using REAL key type
zzv = gettable(tabc, tp1);
// check the value
TEST_CHECK( object_cast<int>(zzv) == 5 );
// the previous call FAILS with
// Terminated with exception: "unable to make cast"
// this is because gettable() doesn't return
// a TRUE value, but nil instead
}
Hopefully, someone smarter than me can figure this out,
Thx
I've traced the problem to the fact that Luabind creates a NEW DISTINCT object EVERY time you use a complex value as key (but it does NOT if you use a primitive one or an object).
Here's a small test case that demonstrates this:
struct test_param : wrap_base
{
int obj;
bool operator==(test_param const& rhs) const
{ return obj == rhs.obj ; }
};
void test_main(lua_State* L)
{
using namespace luabind;
module(L)
[
class_<test_param>("test_param")
.def(constructor<>())
.def_readwrite("obj", &test_param::obj)
.def(const_self == const_self)
];
object tabc, zzk, zzv;
test_param tp;
tp.obj = 123456;
tabc = newtable(L);
// o k v
settable( tabc, tp, 5);
iterator zzi(tabc), end;
std::cerr << "value = " << *zzi << "\n";
zzk = zzi.key();
// o k v
settable( tabc, tp, 6);
settable( tabc, zzk, 7);
for (zzi = iterator(tabc); zzi != end; ++zzi)
{
std::cerr << "value = " << *zzi << "\n";
}
}
Notice how tabc[tp] first has the value 5 and then is overwritten with 7 when accessed through the key object. However, when accessed AGAIN through tp, a new entry gets created. This is why gettable() fails subsequently.
Thx,
David

Disclaimer: I'm not an expert on luabind. It's entirely possible I've missed something about luabind's capabilities.
First of all, what is luabind doing when converting test_param to a Lua key? The default policy is copy. To quote the luabind documentation:
This will make a copy of the parameter. This is the default behavior when passing parameters by-value. Note that this can only be used when passing from C++ to Lua. This policy requires that the parameter type has an accessible copy constructor.
In pratice, what this means is that luabind will create a new object (called "full userdata") which is owned by the Lua garbage collector and will copy your struct into it. This is a very safe thing to do because it no longer matters what you do with the c++ object; the Lua object will stick around without really any overhead. This is a good way to do bindings for by-value sorts of objects.
Why does luabind create a new object each time you pass it to Lua? Well, what else could it do? It doesn't matter if the address of the passed object is the same, because the original c++ object could have changed or been destroyed since it was first passed to Lua. (Remember, it was copied to Lua by value, not by reference.) So, with only ==, luabind would have to maintain a list of every object of that type which had ever been passed to Lua (possibly weakly) and compare your object against each one to see if it matches. luabind doesn't do this (nor do I think should it).
Now, let's look at the Lua side. Even though luabind creates two different objects, they're still equal, right? Well, the first problem is that, besides certain built-in types, Lua can only hold objects by reference. Each of those "full userdata" that I mentioned before is actually a pointer. That means that they are not identical.
But they are equal, if we define an __eq meta operation. Unfortunately, Lua itself simply does not support this case. Userdata when used as table keys are always compared by identity, no matter what. This actually isn't special for userdata; it is also true for tables. (Note that to properly support this case, Lua would need to override the hashcode operation on the object in addition to __eq. Lua also does not support overriding the hashcode operation.) I can't speak for the authors of Lua why they did not allow this (and it has been suggested before), but there it is.
So, what are the options?
The simplest thing would be to convert test_param to an object once (explicitly), and then use that object to index the table both times. However, I suspect that while this fixes your toy example, it isn't very helpful in practice.
Another option is simply not to use such types as keys. Actually, I think this is a very good suggestion, since this kind of light-weight binding is quite useful, and the only other option is to discard it.
It looks like you can define a custom conversion on your type. In your example, it might be reasonable to convert your type to a Lua number which will behave well as a table index.
Use a different kind of binding. There will be some overhead, but if you want identity, you'll have to live with it. It sounds like luabind has some support for wrappers, which you may need to use to preserve identity:
When a pointer or reference to a registered class with a wrapper is passed to Lua, luabind will query for it's dynamic type. If the dynamic type inherits from wrap_base, object identity is preserved.

Related

what /can/ you return from a function .. and expect it to be alive at arrival?

Once again I got cought on expecting a function to return a proper value and then be disapointed .. getting odd behavior and misleading debug-information instead.
It's fairly well known, that you cannot return a local variable from a function and expect it to arrive as you would expect. Testing
int i=2;
int k=4;
return make_pair<int,int>(i*i,k*k);
Does indeed return something respectable. But using more elaborate objects than simple types seems to catch me every time.
So, is there any formality that I can use for discriminating on what can and what cannot be returned safely from a function?
----------- added on edit: ------------
Here is the example that does not work, taken brutally out of context.
Problem-context is a (to be GUI) tree of rectangles for the screen.
Class node inherits from a base (rectangle) containing 3 pointers to plain types (again, used to make values stick) .. the base uses new in constructor
pair<node,node> node_handler::split( vector<node>::iterator& this_node, double ratio, bool as_horizontal ){
//this_node becomes parents to the split-twins
this_node->my_ratio=ratio;
double firstW, firstH;
double secW, secH;
glm::dvec2 afirst, asecond;
if(as_horizontal ){
firstW = *this_node->plWidth*LETTER_PIXEL_WIDTH;
firstH = *this_node->plHeight*LINE_PIXEL_HEIGHT*ratio;
afirst = *this_node->pPoint;
secW = firstW;
secH = LINE_PIXEL_HEIGHT*(*this_node->plHeight)*(1.0d-ratio);
asecond= afirst+glm::dvec2(0.0d, firstH);
}
else{
firstW = ratio*(*this_node->plWidth)*LETTER_PIXEL_WIDTH;
firstH = *this_node->plHeight*LINE_PIXEL_HEIGHT;
afirst = *this_node->pPoint;
secW = (1.0d*ratio)*(*this_node->plWidth)*LETTER_PIXEL_WIDTH;
secH = firstH;
asecond= afirst+glm::dvec2(firstW,0.0d);
}
return make_pair<node,node>( node(afirst ,firstW, firstH) , node(asecond ,secW, secH) ) ;
}
Technically, you can return anything from a function.
Now when you return a pointer or a reference to something that is only local, then you have a problem.
Solutions:
Return copies (OK with copy elision anyway)
Return shared_ptr<>/unique-ptr<> for something that must not be copied.
Return only basic types and pass to the function a reference to an object that might be modified.
Do not create something in the function that needs to be manually destroyed layer (say, a pointer created with new).
It's dawning on me, that classes containing pointer-members reasonably has to have custom copy/assignment operators. I never got to grips with the "rho" variable referred to in the books I read at the time ... "right_hand_object" it must be! That's my epiphany. It was following the business of the constructors and your talk of copyable objects that squeezed this old rho-problem of mine.
I'm sorry for having spread my frustration on you.

How to copy an object if (and only if) it has a copy constructor?

Context: I'm trying to memoize an object of a template class. Right now, the class is a deeply nested data structure full of unique pointers, and so doesn't have a copy constructor (and so would be impossible to cache, as far as I know). However, in the future, I would like to allow memoization if a copy constructor is available. I tried the following code:
// some function here... {
static std::unordered_map<State, Result> cache;
return [c, ToValue](State state) {
if (cache.find(state) != cache.end()) {
std::cout << "retrieving Literal from cache\n";
if (std::is_copy_constructible<Result>::value) {
return cache[state];
}
}
// calculate and return a Result
This code doesn't compile because Result doesn't have a copy constructor. Is there any way to get around this? Google is being quite unhelpful.
I'm presuming the error you are getting is that return cache[state]; cannot be compiled when the object is not copy-constructible. To fix that you can write:
if constexpr (std::is_copy_constructible<Result>::value) {
return cache[state];
}
If you are still having trouble then post a MCVE that has the error.
As others have commented, the question is rather ill-defined and a bit confused, but do you need to actually copy an object in order to cache it?
Actually, no. You can use std::shared_ptr to share ownership of the object between the creator, any consumers, and the cache. If nothing else, this is much more efficient if your object is a complex one. It will also work for any type of object, copyable or not.
Example (I'm going to use the word Key rather than State, for what I hope are obvious reasons).
Given these declarations:
class MyKey
{
// ....
};
class MyCacheableObject
{
// Constructor
MyCacheableObject (int a, int b, int c) { ... }
// ...
};
static std::unordered_map<MyKey, std::shared_ptr<MyCacheableObject>> cache; // or std::map
You can do this (please note that there are other ways to make a std::shared_ptr, see here):
std::shared_ptr<MyCacheableObject> CreateCacheableObject (int a, int b, int c)
{
return std::make_shared<MyCacheableObject> (MyCacheableObject (a, b, c));
}
And then, assuming you have a key you plan to use to retrieve the object from the cache later on, you can do:
MyKey someKey = ...;
std::shared_ptr<MyCacheableObject> newObject = CreateCacheableObject (1, 2, 3);
// ... setup / use `newObject` in whatever way is appropriate to your use-case
cache [someKey] = newObject;
And you can of course retrieve the object from the cache (if it's in there) via:
auto retrievedObject = cache.find (someKey)
if (retrievedObject != cache.end())
...
So this question is not about whether an object is copyable at all. It's about (shared) ownership and std::shared_ptr takes care of all that for you, you don't really have to think about it. Oy vay.
There's a live demo, to show that this all compiles, here.

How can I calculate a hash/checksum/fingerprint of an object in c++?

How can I calculate a hash/checksum/fingerprint of an object in c++?
Requirements:
The function must be 'injective'(*). In other words, there should be no two different input objects, that return the same hash/checksum/fingerprint.
Background:
I am trying to come up with a simple pattern for checking whether or not an entity object has been changed since it was constructed. (In order to know which objects need to be updated in the database).
Note that I specifically do not want to mark the object as changed in my setters or anywhere else.
I am considering the following pattern: In short, every entity object that should be persisted, has a member function "bool is_changed()". Changed, in this context, means changed since the objects' constructor was called.
Note: My motivation for all this is to avoid the boilerplate code that comes with marking objects as clean/dirty or doing a member by member comparison. In other words, reduce risk of human error.
(Warning: psudo c++ code ahead. I have not tried compiling it).
class Foo {
private:
std::string my_string;
// Assume the "fingerprint" is of type long.
long original_fingerprint;
long current_fingerprint()
{
// *** Suggestions on which algorithm to use here? ***
}
public:
Foo(const std::string& my_string) :
my_string(my_string)
{
original_fingerprint = current_fingerprint();
}
bool is_changed() const
{
// If new calculation of fingerprint is different from the one
// calculated in the constructor, then the object has
// been changed in some way.
return current_fingerprint() != original_fingerprint;
}
void set_my_string(const std::string& new_string)
{
my_string = new_string;
}
}
void client_code()
{
auto foo = Foo("Initial string");
// should now return **false** because
// the object has not yet been changed:
foo.is_changed();
foo.set_my_string("Changed string");
// should now return **true** because
// the object has been changed:
foo.is_changed();
}
(*) In practice, not necessarily in theory (like uuids are not unique in theory).
You can use the CRC32 algorithm from Boost. Feed it with the memory locations of the data you want to checksum. You could use a hash for this, but hashes are cryptographic functions intended to guard against intentional data corruption and are slower. A CRC performs better.
For this example, I've added another data member to Foo:
int my_integer;
And this is how you would checksum both my_string and my_integer:
#include <boost/crc.hpp>
// ...
long current_fingerprint()
{
boost::crc_32_type crc32;
crc32.process_bytes(my_string.data(), my_string.length());
crc32.process_bytes(&my_integer, sizeof(my_integer));
return crc32.checksum();
}
However, now we're left with the issue of two objects having the same fingerprint if my_string and my_integer are equal. To fix this, we should include the address of the object in the CRC, since C++ guarantees that different objects will have different addresses.
One would think we can use:
process_bytes(&this, sizeof(this));
to do it, but we can't since this is an rvalue and thus we can't take its address. So we need to store the address in a variable instead:
long current_fingerprint()
{
boost::crc_32_type crc32;
void* this_ptr = this;
crc32.process_bytes(&this_ptr, sizeof(this_ptr));
crc32.process_bytes(my_string.data(), my_string.length());
crc32.process_bytes(&my_integer, sizeof(my_integer));
return crc32.checksum();
}
Such a function does not exist, at least not in the context that you are requesting.
The STL provides hash functions for basic types (std::hash), and you could use these to implement a hash function for your objects using any reasonable hashing algorithm.
However, you seem to be looking for an injective function, which causes a problem. Essentially, to have an injective function, it would be necessary to have an output of size greater or equal to that of the object you are considering, since otherwise (from the pigeon hole principle) there would be two inputs that give the same output. Given that, the most sensible option would be to just do a straight-up comparison of the object to some sort of reference object.

Is it possible to export/wrap a complex Go struct to C?

I own a Go library, gofileseq, for which I would like to try and made a C/C++ binding.
It is pretty straightforward to be able to export functions that use simple types (ints, strings, ...). It is even easy enough to export data from custom Go types to C by defining a C struct and translating the Go type to it, to be used in the exported functions, since you are allocating C memory to do it. But with the go 1.5 cgo rules I am finding it difficult to figure out how to export functionality from a more complex struct that stores state.
Example of a struct from gofileseq that I would like to export somehow to a C++ binding:
// package fileseq
//
type FrameSet struct {
frange string
rangePtr *ranges.InclusiveRanges
}
func NewFrameSet(frange string) (*FrameSet, error) {
// bunch of processing to set up internal state
}
func (s *FrameSet) Len() int {
return s.rangePtr.Len()
}
// package ranges
//
type InclusiveRanges struct {
blocks []*InclusiveRange
}
type InclusiveRange struct {
start int
end int
step int
cachedEnd int
isEndCached bool
cachedLen int
isLenCached bool
}
As you can see, the FrameSet type that I want to expose contains a slice of pointers to an underlying type, each of which stores state.
Ideally, I would love to be able to store a void* on a C++ class, and make it just a simple proxy for calling back into exported Go functions with the void*. But the cgo rules disallow C storing a Go pointer longer than the function call. And I am failing to see how I could use an approach of defining C++ classes that could be allocated and used to operate with my Go library.
Is it possible to wrap complex types for exposure to C/C++?
Is there a pattern that would allow a C++ client to create a Go FrameSet?
Edit
One idea I can think of would be to let C++ create objects in Go that get stored on the Go side in a static map[int]*FrameSet and then return the int id to C++. Then all the C++ operations make requests into Go with the id. Does that sound like a valid solution?
Update
For now, I am proceeding with testing a solution that uses global maps and unique ids to store objects. C++ would request a new object to be created and only get back an opaque id. Then they can call all of the methods exported as functions, using that id, including requesting for it to be destroyed when done.
If there is a better approach than this, I would love to see an answer. Once I get a fully working prototype, I will add my own answer.
Update #2
I've written a blog post about the final solution that I ended up using: http://justinfx.com/2016/05/14/cpp-bindings-for-go/
The way I ended up solving this, for lack of a better solution, was to use private global maps on the Go side (ref). These maps would associate instances of the Go objects with a random uint64 id, and the id would be returned to C++ as an "opaque handle".
type frameSetMap struct {
lock *sync.RWMutex
m map[FrameSetId]*frameSetRef
rand idMaker
}
//...
func (m *frameSetMap) Add(fset fileseq.FrameSet) FrameSetId {
// fmt.Printf("frameset Add %v as %v\n", fset.String(), id)
m.lock.Lock()
id := FrameSetId(m.rand.Uint64())
m.m[id] = &frameSetRef{fset, 1}
m.lock.Unlock()
return id
}
Then I use reference counting to determine when C++ no longer needs the object, and remove it from the map:
// Go
func (m *frameSetMap) Incref(id FrameSetId) {
m.lock.RLock()
ref, ok := m.m[id]
m.lock.RUnlock()
if !ok {
return
}
atomic.AddUint32(&ref.refs, 1)
// fmt.Printf("Incref %v to %d\n", ref, refs)
}
func (m *frameSetMap) Decref(id FrameSetId) {
m.lock.RLock()
ref, ok := m.m[id]
m.lock.RUnlock()
if !ok {
return
}
refs := atomic.AddUint32(&ref.refs, ^uint32(0))
// fmt.Printf("Decref %v to %d\n", ref, refs)
if refs != 0 {
return
}
m.lock.Lock()
if atomic.LoadUint32(&ref.refs) == 0 {
// fmt.Printf("Deleting %v\n", ref)
delete(m.m, id)
}
m.lock.Unlock()
}
//C++
FileSequence::~FileSequence() {
if (m_valid) {
// std::cout << "FileSequence destroy " << m_id << std::endl;
m_valid = false;
internal::FileSequence_Decref(m_id);
m_id = 0;
m_fsetId = 0;
}
}
And all C++ interactions with the exported Go library communicate via the opaque handle:
// C++
size_t FileSequence::length() const {
return internal::FileSequence_Len(m_id);
}
Unfortunately it does mean that in a multhreaded C++ environment, all threads would go through a mutex to the map. But it is only a write lock when objects are created and destroyed, and for all method calls on an object it is a read lock.

Prevent v8::Local value from being garbage collected

I have a function that stores the value of an argument to an std::vector<v8::Local<v8::Value>> property of a C++ class exposes as an ObjectWrap like this:
NAN_METHOD(MyObject::Write) {
MyObject* obj = Nan::ObjectWrap::Unwrap<MyObject>(info.This());
obj->data.push_back(info[0]);
}
However, when I try to read back the value from another C++ function, the value is lost, and becomes undefined.
I'm passing a number to MyObject::Write, and I can confirm info[0]->IsNumber() returns true before pushing it to the vector, however when reading it back, the value it not a number, and in fact returns false for all the types I tested using Is<Type> methods from v8::Value, but still returns true for BooleanValue().
My guess is that the variable is being garbage collected after MyObject::Write returns, however I have no idea how to prevent this from happening.
I'm currently trying to initialise the value as a Persistent value. I tried the following attempts without success:
Nan::CopyablePersistentTraits<v8::Value>::CopyablePersistent p;
Nan::Persistent<v8::Value> persistent(info[0]);
Nan::CopyablePersistentTraits::Copy(persistent, p);
And:
v8::Isolate *isolate = info.GetIsolate();
v8::Persistent<v8::Value, v8::CopyablePersistentTraits<v8::Value>> persistent(isolate, info[0]);
But getting tons of C++ errors.
I was running into problems untangling this mess myself. There's a lot of template stuff going on here that we both missed. Here was the solution I found most readable:
// Define the copyable persistent
v8::CopyablePersistentTraits<v8::Value>::CopyablePersistent p;
// Create the local value
auto val = v8::Local<v8::Value>::New(
v8::Isolate::GetCurrent(), //< Isolate required
v8::Integer::New(v8::Isolate::GetCurrent(), v) //< Isolate required
);
// Reset() is a TEMPLATE FUNCTION, you have to template it with the same
// template type parameter as the v8::Local you are passing
p.Reset<v8::Value>(v8::Isolate::GetCurrent(), val); //< Isolate required
By "info" I assume you are referring to a v8::FunctionCallbackInfo reference. If so the above code would collapse to the following:
void SomeFunc(v8::FunctionCallbackInfo<v8::Value>& info) {
v8::CopyablePersistentTraits<v8::Value>::CopyablePersistent p;
p.Reset<v8::Value>(info[0]);
}
Because the persistent is now copyable you can do things like store it inside a standard library container. This was my use case. This is an example of storing a value in a vector:
std::vector<v8::CopyablePersistentTraits<v8::Value>::CopyablePersistent> vect;
void AccumulateData(v8::FunctionCallbackInfo<v8::Value>& info) {
v8::CopyablePersistentTraits<v8::Value>::CopyablePersistent p;
p.Reset<v8::Value>(info[0]);
vect.push_back(p);
}
I hope this helps someone out there.
If you plan on storing v8 values in C++, you need to make them persistent instead of local so they're independent of handle scope and not garbage-collected when the handle scope is released.
Nan has version-independant wrappers for v8::Persistent and Co. Because of using inside std::vector<>, you'll also need to initialize Nan::Persistent with Nan::CopyablePersistentTraits so it becomes copyable (or make an own reference-counted container for it).