Currently I'm trying to convert a py::dict into its counterpart C++s std::map. Trying to use the
automatic conversion like this fails :
#include <pybind11/stl.h>
namespace py = pybind11;
using namespace py::literals;
...
py::dict py_kwargs = py::dict("number1"_a = 5, "number2"_a = 42);
auto cpp_kwargs = py_kwargs.cast<std::map<int, int>>();
with an exception stating :
Unable to cast Python instance of type <class 'dict'> to C++ type 'std::map<int,int,std::less<int>,std::allocator<std::pair<int const ,int> > >'
What am I missing here?
Also on a side note, how should I go about the situation , where the python dictionary has different key types, for example like :
py::dict py_kwargs = py::dict("name"_a = "World", "number"_a = 42);
How should I go about the conversion in such cases?
OK, I found the issue, before that I ended up doing the conversion like this :
map<std::string, int> convert_dict_to_map(py::dict dictionary)
{
map<std::string, int> result;
for (std::pair<py::handle, py::handle> item : dictionary)
{
auto key = item.first.cast<std::string>();
auto value = item.second.cast<int>();
//cout << key << " : " << value;
result[key] = value;
}
return result;
}
and then, looked carefully at the :
auto cppmap = kwargs.cast<map<int, int>>();
and finally noticed my issue.
it should have been :
auto cppmap = kwargs.cast<map<std::string, int>>();
I made a mistake, when I changed my example dict and later on reverted back the changes but forgot to change the signature!
Anyway, it seems the first solution may be a better choice, as it allows the developer to work with Python's dynamic nature better.
That is, a Python dictionary may very well, include different pairs (such as string:string, string:int, int:float, etc all in the same dictionary object). Therefore, making sure the items are validly reconstructed in c++ can be done much better using the first crude method!
Related
I would like to learn Kotlin and try to transfer multiple objects that each manage two ints to one list that manages a hashmap of two ints.
This is the new object:
public class HashObject(val maps: MutableList<HashMap<Int, Int>>){
...
}
This is the old object:
public class OldObject(
val a: Int,
val b: Int
)
I have a list of the old objects:
val oldObjects: List<OldObject> = ...
And i am trying to transfer it like this:
val hashObjects = mutableListOf<HashMap<Int, Int>>()
for(obj in oldObjects){
hashObjects.add(hashMapOf(obj.a to obj.b))
val result = HashObject(maps = hashObjects)
But I get the following error:
Type mismatch.
Required: kotlin.collections.HashMap<Int, Int> /* = java.util.HashMap<Int, Int> */
Found: MutableList<java.util.HashMap<Int, Int>>
How can I solve this problem?
Another way to do what you're asking is
val result = oldObjects.map { oldObj -> hashMapOf(oldObj.a to oldObj.b) }
.toMutableList()
The question seems a bit confused, but I suspect that what's really needed is a single map from Int to Int. One of the simplest (and most efficient) ways to get that is:
val result = oldObjects.associate{ it.a to it.b }
That gives a Map<Int, Int>, with one entry for each of the original OldObjects. (With the caveat that if multiple OldObjects have the same key, only the last will be included in the result. If you need to preserve them all in that case, then a map isn't the right structure.)
(If you need the result to be mutable, you can then call toMutableMap() on it — but in general it's simpler and safer to stick to immutable objects where possible.)
I have this code:
enum EXECUTION_COMMANDS {
"buy" = OP_BUY,
"sell" = OP_SELL,
"buyLimit" = OP_BUYLIMIT,
"sellLimit" = OP_SELLLIMIT,
"buyStop" = OP_BUYSTOP,
"sellStop" = OP_SELLSTOP
};
So basically what I want to create is when program sees the string "buy", it has to read it as OP_BUY. Since OP_BUY is an internal command on MQL4, how do I do this? Is there another way to do this?
enum EXECUTION_COMMANDS
{
buy = OP_BUY,
...
};
Now the identifier buy is basically a named integer constant with the same value as OP_BUY. You can use buy and OP_BUY as aliases for each other.
If you really want to use strings then you need to create a map, that maps the strings into their integer values:
std::unordered_map<std::string, int> command_map = {
{ "buy", OP_BUY },
...
};
Then to use it use command_map["buy"] which will return the int value of OP_BUY.
Just take out the quotes.
The names of the enumerators should be identifiers, not strings.
enum EXECUTION_COMMANDS
{
buy = OP_BUY,
sell = OP_SELL,
buyLimit = OP_BUYLIMIT,
sellLimit = OP_SELLLIMIT,
buyStop = OP_BUYSTOP,
sellStop = OP_SELLSTOP
};
But if you wanted this to replace actual string literals in your source code, you're going to be disappointed. Either do not use string literals or, if you can't change the input being strings, introduce some mapping using a std::map<std::string, int>.
I have a C++ function which takes a vector< pair< pair<string,string>, string > > which I wish to call from python.
I wrote a wrapper as below:
bool create_cache_wrapper(boost::python::tuple tup_)
{
vector< pair< pair<string,string>, string > > rbv;
for(int i=0;i<py::len(tup_);++i)
{
std::string start,end,bucket;
bucket = py::extract<std::string>(tup_[i][1]);
start = py::extract<std::string>(tup_[i][0][0]);
end = py::extract<std::string>(tup_[i][0][1]);
rbv.push_back(make_pair(make_pair(start,end),bucket));
}
return create_cache(rbv);
}
I have registered this function with python as below:
BOOST_PYTHON_MODULE(my_lib)
{
using namespace boost::python;
def("create_cache", create_cache_wrapper);
}
This works fine but the issue is, it accepts only a tuple but not a list. How do I write the wrapper such that it works any sequence container in python? Is there a better way to do this without having to write a wrapper? I want the python api to be simple like
create_cache( ( (('',''),'b1'), ) )
create_cache( [ (('',''),'b1') ] )
This could be accomplished by making the wrapper take an object instead:
bool create_cache_wrapper(boost::python::object tup_)
{
// ...
}
py::len() and the indexing operators should work on objects, and they should raise a Python error if the type in question does not support len() or indexing. This should allow the caller to provide any indexable type, even user-defined ones!
I normally use boost python iterator wrappers to achieve what you described - it works with any type of iterable. I adapted your code below so you have an idea on how to do it yourself:
#include <boost/python.hpp>
#include <boost/python/stl_iterator.hpp>
using namespace boost::python;
bool create_cache_wrapper(object iterable)
{
stl_input_iterator<object> end;
for(std_input_iterator<object> i(iterable); i!=end; ++i)
{
std::string start,end,bucket;
bucket = py::extract<std::string>((*i)[1]);
start = py::extract<std::string>((*i)[0][0]);
end = py::extract<std::string>((*i)[0][1]);
rbv.push_back(make_pair(make_pair(start,end),bucket));
}
return create_cache(rbv);
}
You can go all the way using stl_input_iterator, even for the your pairs inside the first iterable.
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.
I'm a newbie at using the STL Algorithms and am currently stuck on a syntax error. My overall goal of this is to filter the source list like you would using Linq in c#. There may be other ways to do this in C++, but I need to understand how to use algorithms.
My user-defined function object to use as my function adapter is
struct is_Selected_Source : public std::binary_function<SOURCE_DATA *, SOURCE_TYPE, bool>
{
bool operator()(SOURCE_DATA * test, SOURCE_TYPE ref)const
{
if (ref == SOURCE_All)
return true;
return test->Value == ref;
}
};
And in my main program, I'm using as follows -
typedef std::list<SOURCE_DATA *> LIST;
LIST; *localList = new LIST;;
LIST* msg = GLOBAL_DATA->MessageList;
SOURCE_TYPE _filter_Msgs_Source = SOURCE_TYPE::SOURCE_All;
std::remove_copy(msg->begin(), msg->end(), localList->begin(),
std::bind1st(is_Selected_Source<SOURCE_DATA*, SOURCE_TYPE>(), _filter_Msgs_Source));
What I'm getting the following error in Rad Studio 2010. The error means "Your source file used a typedef symbol where a variable should appear in an expression. "
"E2108 Improper use of typedef 'is_Selected_Source'"
Edit -
After doing more experimentation in VS2010, which has better compiler diagnostics, I found the problem is that the definition of remove_copy only allows uniary functions. I change the function to uniary and got it to work.
(This is only relevant if you didn't accidentally omit some of your code from the question, and may not address the exact problem you're having)
You're using is_Selected_Source as a template even though you didn't define it as one. The last line in the 2nd code snippet should read std::bind1st(is_Selected_Source()...
Or perhaps you did want to use it as a template, in which case you need to add a template declaration to the struct.
template<typename SOURCE_DATA, typename SOURCE_TYPE>
struct is_Selected_Source : public std::binary_function<SOURCE_DATA *, SOURCE_TYPE, bool>
{
// ...
};
At a guess (though it's only a guess) the problem is that std::remove_copy expects a value, but you're supplying a predicate. To use a predicate, you want to use std::remove_copy_if (and then you'll want to heed #Cogwheel's answer).
I'd also note that:
LIST; *localList = new LIST;;
Looks wrong -- I'd guess you intended:
LIST *locallist = new LIST;
instead.