Type Conversion Error in Coos2dx - cocos2d-x

I am try to convert http://www.raywenderlich.com/29460/collisions-and-collectables-how-to-make-a-tile-based-game-with-cocos2d-2-x-part-2 tutorial into cocos2dx and getting error
in this line:
CCString *collision = properties->objectForKey("Collidable");
void HelloWorld::setPlayerPosition(CCPoint position)
{
CCPoint tileCoord = this->tileCoordForPosition(position);
int tileGid = _meta->tileGIDAt(tileCoord);
if(tileGid)
{
CCDictionary *properties = _tileMap->propertiesForGID(tileGid);
if(properties)
{
CCString *collision = properties->objectForKey("Collidable");
if(collision && (collision->compare("True")))
return;
}
}
_player->setPosition(position);
}

The compiler complains about the loss of "const-ness" of the CCString. The objectForKey method returns a const CCString* but you're assigning it to a CCString* which means it's no longer const.
You have three options to fix this, starting with the easiest:
Declare your CCString const (no downsides to this other than not being able to assign another CCString to the same object):
const CCString *collision = properties->objectForKey("Collidable");
Explicitly cast const away (this may not be allowed depending on compiler settings):
CCString *collision = (CCString*)properties->objectForKey("Collidable");
Remove the permissive flag from compiler settings to ignore this error. Not recommended because it allows you to violate const-ness.

Related

Using SWIG to wrap structures containing const char * without memory leak

I'm attempting to use SWIG to wrap a pre-existing library interface that expects the caller to manage the lifetime of some const char * values.
struct Settings {
const char * log_file;
int log_level;
};
// The Settings struct and all members only need to be valid for the duration of this call.
int Initialize(const struct Settings* settings);
int DoStuff();
int Deinitialize();
I started off using the most basic input to SWIG to wrap the library:
%module lib
%{
#include "lib.h"
%}
%include "lib.h"
This leads to SWIG warning about a potential memory leak:
lib.h(2) : Warning 451: Setting a const char * variable may leak memory.
Which is entirely understandable as looking at lib_wrap.c, SWIG has generated code that will malloc a buffer into the log_file value but never frees it:
SWIGINTERN PyObject *_wrap_Settings_log_file_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
PyObject *resultobj = 0;
struct Settings *arg1 = (struct Settings *) 0 ;
char *arg2 = (char *) 0 ;
void *argp1 = 0 ;
int res1 = 0 ;
int res2 ;
char *buf2 = 0 ;
int alloc2 = 0 ;
PyObject *swig_obj[2] ;
if (!SWIG_Python_UnpackTuple(args, "Settings_log_file_set", 2, 2, swig_obj)) SWIG_fail;
res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_Settings, 0 | 0 );
if (!SWIG_IsOK(res1)) {
SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Settings_log_file_set" "', argument " "1"" of type '" "struct Settings *""'");
}
arg1 = (struct Settings *)(argp1);
res2 = SWIG_AsCharPtrAndSize(swig_obj[1], &buf2, NULL, &alloc2);
if (!SWIG_IsOK(res2)) {
SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Settings_log_file_set" "', argument " "2"" of type '" "char const *""'");
}
arg2 = (char *)(buf2);
if (arg2) {
size_t size = strlen((const char *)((const char *)(arg2))) + 1;
arg1->log_file = (char const *)(char *)memcpy(malloc((size)*sizeof(char)), arg2, sizeof(char)*(size));
} else {
arg1->log_file = 0;
}
resultobj = SWIG_Py_Void();
if (alloc2 == SWIG_NEWOBJ) free((char*)buf2);
return resultobj;
fail:
if (alloc2 == SWIG_NEWOBJ) free((char*)buf2);
return NULL;
}
If I change the type of log_file to char * then the warning goes away and it appears that multiple attempts to set the value of log_file will no longer leak memory:
SWIGINTERN PyObject *_wrap_Settings_log_file_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
PyObject *resultobj = 0;
struct Settings *arg1 = (struct Settings *) 0 ;
char *arg2 = (char *) 0 ;
void *argp1 = 0 ;
int res1 = 0 ;
int res2 ;
char *buf2 = 0 ;
int alloc2 = 0 ;
PyObject *swig_obj[2] ;
if (!SWIG_Python_UnpackTuple(args, "Settings_log_file_set", 2, 2, swig_obj)) SWIG_fail;
res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_Settings, 0 | 0 );
if (!SWIG_IsOK(res1)) {
SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Settings_log_file_set" "', argument " "1"" of type '" "struct Settings *""'");
}
arg1 = (struct Settings *)(argp1);
res2 = SWIG_AsCharPtrAndSize(swig_obj[1], &buf2, NULL, &alloc2);
if (!SWIG_IsOK(res2)) {
SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Settings_log_file_set" "', argument " "2"" of type '" "char *""'");
}
arg2 = (char *)(buf2);
if (arg1->log_file) free((char*)arg1->log_file);
if (arg2) {
size_t size = strlen((const char *)(arg2)) + 1;
arg1->log_file = (char *)(char *)memcpy(malloc((size)*sizeof(char)), (const char *)(arg2), sizeof(char)*(size));
} else {
arg1->log_file = 0;
}
resultobj = SWIG_Py_Void();
if (alloc2 == SWIG_NEWOBJ) free((char*)buf2);
return resultobj;
fail:
if (alloc2 == SWIG_NEWOBJ) free((char*)buf2);
return NULL;
}
However it still appears that the memory allocated for log_file will be leaked when the Settings object is garbage collected in Python.
What is the recommended way of managing lifetimes of char * struct values in SWIG in a way which avoids these memory leaks?
Strings are a bit awkward to do right here. There are several ways to side-step the issue you're seeing. Simplest is to use a fixed size array in the struct, but it's 2019. Personally I'd wholeheartedly recommend using idiomatic C++ instead (it's 2019!), which would mean std::string and then the whole issue evaporates.
Failing that you're stuck in a case where to make the interface Pythonic you'll have to do some extra work. We can keep the total amount of work low and the nice thing about SWIG is that we can pick and choose where we target the extra effort we make, there's no "all or nothing". The main problem here is that we want to tie the lifespan of the buffer the log_file path is stored in to the lifespan of the Python Settings object itself. We can achieve that in multiple different ways depending on your preference for writing Python code, C or Python C API calls.
What we can't really solve is the case were you're given a borrowed pointer to a Settings struct by some other code (i.e. it's not owned/managed by Python) and you want to change log_file string in that borrowed object. The API you've got doesn't really give us a way to do that, but it seems like this isn't a case that really matters in your current module.
So without further ado below are a few options for tying the lifespan of a buffer that holds your string to a Python object that points to the buffer.
Option #1: Make Settings wholly or partially immutable, use a single malloc call to hold both the struct itself and the string it refers to. For this use case that's probably my preferred option.
We can do that fairly simply by giving the Settings type a constructor in Python which handles this and it doesn't force you to use C++:
%module lib
%{
#include "lib.h"
%}
// Don't let anybody change this other than the ctor
%immutable Settings::log_file;
%include "lib.h"
%extend Settings {
Settings(const char *log_file) {
assert(log_file); // TODO: handle this properly
// Single allocation for both things means the single free() is sufficient and correct
struct Settings *result = malloc(strlen(log_file) + 1 + sizeof *result);
char *buf = (void*)&result[1];
strcpy(buf, log_file);
result->log_file = buf;
return result;
}
}
If you wanted to make the path mutable you could write a little extra Python code that wraps this up and acts a proxy which creates a new immutable object every time you "mutate" it on the Python side. You could also go the other way and make the other members of settings immutable. (Thinking about it some more it'd be neat if SWIG could optionally auto synthesize a kwargs constructor for aggregate/POD types and wouldn't be too hard to add that as a patch).
This is my personal preference here, I like immutable things and overall it's a fairly small tweak to the generated interface to get something sane.
Option #2a: Make another Python object that manages the lifespan of the string buffer and then "stash" a reference to that inside the Python side of every Settings struct that's owned by Python.
%module lib
%{
#include "lib.h"
%}
%typemap(in) const char *log_file %{
// Only works for Python owned objects:
assert(SWIG_Python_GetSwigThis($self)->own & SWIG_POINTER_OWN); // TODO: exception...
// Python 2.7 specific, 3 gets more complicated, use bytes buffers instead.
$1 = PyString_AsString($input);
assert($1); // TODO: errors etc.
// Force a reference to the original input string to stick around to keep the pointer valid
PyObject_SetAttrString($self, "_retained_string", $input);
%}
%typemap(memberin) const char *log_file %{
// Because we trust the in typemap has retained the pointer for us this is sufficient now:
$1 = $input;
%}
%include "lib.h"
These typemaps work together to keep a reference to the PyObject string stashed inside the Settings PyObject as an attribute. It only works safely here because a) we assume Python owns the object, and we're not using -builtin in SWIG, so we can safely stash things in attributes to keep them around and b) because it's const char *, not char * we can be pretty sure that (unless there's some K&R silliness going on) that nobody will be changing the buffer.
Option #2b: The general idea is the same, but instead of using typemaps, which means writing Python C API calls use something like this:
%extend Settings {
%pythoncode {
#property
# ....
}
}
To do the same thing. Similar code could also be produced using %pythonprepend instead if preferred. However this is my least preferred solution here, so I've not fully fleshed it out.
You can tell SWIG to use char* semantics for log_file. Unfortunately, it doesn't seem possible to use Settings::log_file (the required memberin does not show up in the pattern matching), so there could be clashes if that data member name is used in other structs as well with the same type but different semantics. This would look like:
%module lib
%{
#include "lib.h"
%}
%typemap(out) char const *log_file = char *;
%typemap(memberin) char const *log_file = char *;
%extend Settings {
Settings() {
Settings* self = new Settings{};
self->log_file = nullptr;
self->log_level = 0;
return self;
}
~Settings() {
delete[] self->log_file; self->log_file = nullptr;
delete self;
}
}
%include "lib.h"
(Note that SWIG in my case produces delete[], not free().)
EDIT: added a custom destructor to delete the log_file memory on garbage collection. (And for good measure also a constructor to make sure that an uninitialized log_file is nullptr, not some random memory.) What this does, is add an internal function delete_Settings to the wrapper file, which gets called in _wrap_delete_Settings, which is called on object destruction. Yes, syntax is a bit odd, b/c you're effectively describing Python's __del__ (taking a self), only labeled as a C++ destructor.

Does TypeScript allow a type alias to specify generics?

I would like to be able to alias a very generic function and specify part of the generic parameters, thus creating a less generic version of the same function. Something like the following:
function veryGeneric<X, Y>(someParam: Y): { result: X } {
// ...
}
type LessGeneric = typeof veryGeneric<X, string>
const lessGeneric: LessGeneric = veryGeneric
Where I would want the lessGeneric function to essentially be typed as:
function lessGeneric<X>(someParam: string): { result: X } {
// ...
}
Is this possible in any way?
I know I could create a wrapper function, but I would prefer to not have to specify the parameter typings again (and not having to pay the overhead of another function call, even if it’s tiny, would be a bonus).
Here’s the real example I’m dealing with. Given a function declaration (from react-tracking) like the following:
declare function track<T = {}, P = {}>(trackingInfo?: TrackingInfo<T, P>, options?: Options<Partial<T>>): Decorator
I want to be able to define an alias that specifies the trackingInfo parameter’s typing but leaves P generic. i.e. I want an alias that’s essentially typed as:
interface ValidAnalyticsEntries {
page: string
action: string
}
declare function trackSpecificToOurAnalyticsSchema<P = {}>(trackingInfo?: TrackingInfo<ValidAnalyticsEntries, P>, options?: Options<Partial<ValidAnalyticsEntries>>): Decorator
To define generic type alias you can define an interface describing your function signature:
interface VeryGeneric<X, Y> {
(someParam: Y): { result: X };
}
type Foo = { foo: number };
type LessGeneric<X = Foo> = VeryGeneric<X, string>;
const lessGeneric: LessGeneric = veryGeneric;
You can do this:
const lessGeneric: <X>(someParam: string) => { result: X } = veryGeneric;
I'm just spelling out the desired type of lessGeneric without trying to force TypeScript to convert the type of veryGeneric to the type of lessGeneric first. There's no wrapper function, though.
Does this work for you? If not, please add more detail to your use case and example. Specifically, the X parameter is almost impossible to implement (how can the implementation get its hands on a value of type X) and the Y parameter is doing next to nothing (the someParam argument is of type Y, but nothing else is using Y, so you might as well just declare someParam to be of type any and not use Y).
Hope that helps; good luck!
EDIT: My suggestion for the real example looks like:
const trackSpecificToOurAnalyticsSchema: <P = {}>(
trackingInfo?: TrackingInfo<ValidAnalyticsEntries, P>,
options?: Options<Partial<ValidAnalyticsEntries>>)
=> Decorator = track;
Or, abstracting away from ValidAnalyticsEntries:
type PartiallySpecifiedTrack<T = {}> = <P = {}>(
trackingInfo?: TrackingInfo<T, P>,
options?: Options<Partial<T>>)
=> Decorator
const trackSpecificToOurAnalyticsSchema:
PartiallySpecifiedTrack<ValidAnalyticsEntries> = track;
Note that in all these cases you still have to write out function signature at least two times in total: once when you define the fully generic track(), and once to define PartiallySpecifiedTrack. But you can re-use PartiallySpecifiedTrack with different values for T if you want:
const anotherTrack: PartiallySpecifiedTrack<{ foo: string }> = track;
declare const trackingInfo: TrackingInfo<{ foo: string }, {bar: number}>
anotherTrack(trackingInfo); // okay
Okay, that's the best I can do. Good luck!

AS3: Is it possible to give a vector function argument a default value?

I have a function where I'd like to make a vector argument optional-- that is, something like this:
public function test(arg1:int, arg2:Vector.<int> = new Vector.<int>(5)) {}
So in that example, I want the first argument to be required, and an optional vector passed in. If the second argument is not provided, create an int vector with 5 elements instead. It throws a compile error: "Parameter initializer unknown or is not a compile-time constant."
Making the argument not optional works, as in:
public function test(arg1:int, arg2:Vector.<int>) {}
But that's not exactly what I'm looking for. Doing some searching I found a supposed workaround, which is
public function test(arg1:int, arg2:Vector.<int> = null) {}
But that doesn't compile either.
I've already moved on in my code with a workaround just to be done with it, but I'm still curious. Can you have a vector as a default argument, and how?
I don't think this is possible. Probably just because the compiler was never programmed to handle this situation because optional parameters do work with many other datatypes in AS3. I did some research and other have reported the same issue as you with no success in setting an empty vector object in the function declaration.
I would simply do the following if you haven't already:
var myDefaultVector:Vector.<int> = new Vector.<int>(5);
function test(arg1:int, arg2:Vector.<int> = null) {
if( arg2 == null ) {
arg2 = myDefaultVector;
}
// rest of your code
}
I have tried compiling the above code in Flash and it compiled successfully.

Underscores in MvvmCross data binding

I'm using the fluent syntax and lambdas for data binding in MvvmCross. An example of this is:
var bindings = this.CreateBindingSet<MyTableCell, MyTableCellViewModel>();
bindings.Bind(titleLabel).To(vm => vm.MY_TITLE);
bindings.Apply();
Whenever I try this with an underscore in a view model property I get an exception:
Cirrious.CrossCore.Exceptions.MvxException: Unexpected character _ at
position 3 in targetProperty text MY_TITLE
I believe the error message is a result of MvvmCross parsing the data binding, yet this seems to only make sense for people using string-based data binding, not the lambda expression syntax.
Unfortunately, I cannot change the view models so I'm looking for a workaround to allow underscores in the view models. Any ideas?
I'd guess this is a general problem in the MvvmCross parser - probably in
private void ParsePropertyName()
{
var propertyText = new StringBuilder();
while (!IsComplete && char.IsLetterOrDigit(CurrentChar))
{
propertyText.Append(CurrentChar);
MoveNext();
}
var text = propertyText.ToString();
CurrentTokens.Add(new MvxPropertyNamePropertyToken(text));
}
In https://github.com/MvvmCross/MvvmCross/blob/v3/Cirrious/Cirrious.MvvmCross.Binding/Parse/PropertyPath/MvxSourcePropertyPathParser.cs#L80
Which probably needs to be fixed to something like:
while (!IsComplete &&
(char.IsLetterOrDigit(CurrentChar) || CurrentChar == '_')
There are workarounds you could do, but the easiest solution is probably to fix this and rebuild, rather than to try workarounds.
But if you do want to try workarounds....
Assuming this is static (non-changing) text and this is just a one-off for now, then one workaround might be to add a property to your cell called Hack and to then bind like:
bindings.Bind(this).For(v => v.Hack).To(vm => vm);
//...
private MyTableCellViewModel _hack;
public MyTableCellViewModel Hack
{
get { return _hack; }
set { _hack = value; if (_hack != null) titleLabel.Text = _hack.MY_VALUE; }
}
Another alternative (with the same assumptions) might be to use a value converter -
bindings.Bind(titleLabel).To(vm => vm.MY_TITLE).WithConversion(new WorkaroundConverter(), null);
// ...
public class WorkaroundConverter : MvxValueConverter<MyTableCellViewModel, string>
{
protected override string Convert(MyTableCellViewModel vm, /*...*/)
{
if (vm == null) return null;
return vm.MY_TITLE;
}
}

how to make a map<CLSID, string>?

I want to create a container which can associate a CLSID structure to something else (for example, a string); for example, std::map.
(the CLSID means standard Windows CLSID structure)
However when I want to use its find() and insert (object[clsid] = string), the STL just failed and gives errors.
Does anyone know how to solve this?
For example:
typedef std::map<CLSID, std::string> MyCLSIDMap;
MyCLSIDMap mymap;
CLSID sample = CLSID_NULL;
mymap[sample] = string("test"); // compilation failed here
As Alex has answered, std::map needs to compare it's keys with op<.
bool operator<(CLSID const& l, CLSID const& r)
{
return memcmp(&l, &r, sizeof(CLSID)) < 0;
}
Does your CLSID structure support a usable operator<()? That's crucial for std::map (you can build it as a separate bool functor taking two const CLSID& arguments, it doesn't have to be a method operator<() in CLSID -- but then you'll have to say std::map and not just map ...!).
To use an STL map where the keys are structures, you'll need to provide your own strict weak ordering function object:
struct CompareCLSID
{
bool operator()(const CLSID &s1, const CLSID &s2) const
{
// returns true if s1 is less than s2
}
};
and then your map's type would be map<CLSID, string, CompareCLSID>.
However, if you don't need your container is sorted (that's my guess), you should be using hash<> or hash_map<>. In that case, you'll have to provide your own hash function.