std::vector in objective c method
Solution 1
All correct, and Barry Wark's solution works but I don't recommend it because language-specific pre-processor tricks like this are fragile IMO. In particular, they don't work correctly if there are namespaces involved, and only work on pointers.
First, I strongly recommend that developers keep their ObjC and C++ separate as much as possible and minimize ObjC++ to a few places where it's really needed. ObjC++ is a crazy language that gdb often has trouble with, hurts ARC performance, compiles slower, and generally is mostly a useful-at-times hack rather than a real language.
I recommend this approach to hiding your C++ methods from ObjC in headers:
@interface MyClass
- (void)anOtherMethodCalledFromObjC;
#ifdef __cplusplus
- (void)stitchGroundVectsWithVector:(std::vector<b2Vec2>)vec;
#endif
@end
But generally speaking, I recommend that most of your program be .m and .cpp files, with a few .mm files to glue them together.
For extensive discussion on how to do this in older code, see Wrapping C++-Take 2. Newer code doesn't require ivars to be in the headers, so it should be even simpler to implement today.
Solution 2
As @H2CO3 and @Joshua Weinberg point out, Objective-C++ lets you define a method with an argument of type std::vector
(or a reference thereof, etc.). This will work fine if you're staying within Objective-C++ for all files that include the relevant .h. If, however, you need to import that header into Objective-C-compiled files, you'll need to pass the pointer, and hide the type from Objective-C code:
#ifdef CPLUSPLUS
typedef std::vector* vecp_t
#else
typedef void* vecp_t
#endif
@interface MyClass
{}
- (void)anOtherMethodCalledFromObjC;
- (void)stitchGroundVectsWithVector:(vecp_t)vec;
@end
(I've taken the liberty of Objective-C stylizing your method names)
Solution 3
With Objective-C++ there is no reason you can't just define stichgroundvectswith:
as -(void)stitchgroundvectswith:(std::vector<bVect2>&)vets num:(int)num
just like if you were working in straight C++. C++ objects can be seamlessly (with certain caveats) integrated into Obj-C methods in this mode.
coasty
Updated on June 04, 2022Comments
-
coasty almost 2 years
Im working in objective C++. The issue I am stuck with is that I need to pass a std::vector to an objective c method. Is this possible? Below is my current code where I am having to do my calculations on the vector in the vector definition method (adding an offset value to the members of the array) before passing to the method as a C array. Ideally I would like to set the offset values in the second method, thus splitting up the definition (there will be several of these) The offset will be variable unlike in the example below.
So instead of passing in (b2Vec2 *)vect i want to use vectors
- (void)createterrain1 { using namespace std; vector<b2Vec2>vecVerts; vector<int>::size_type i; vecVerts.push_back(b2Vec2(-1022.5f / 100.0, -20.2f / 100.0)); vecVerts.push_back(b2Vec2(-966.6f / 100.0, -18.0f / 100.0)); vecVerts.push_back(b2Vec2(-893.8f / 100.0, -10.3f / 100.0)); vecVerts.push_back(b2Vec2(-888.8f / 100.0, 1.1f / 100.0)); vecVerts.push_back(b2Vec2(-804.0f / 100.0, 10.3f / 100.0)); vecVerts.push_back(b2Vec2(-799.7f / 100.0, 5.3f / 100.0)); vecVerts.push_back(b2Vec2(-795.5f / 100.0, 8.1f / 100.0)); vecVerts.push_back(b2Vec2(-755.2f/ 100.0, -9.5f / 100.0)); vecVerts.push_back(b2Vec2(-632.2f / 100.0, 5.3f / 100.0)); vecVerts.push_back(b2Vec2(-603.9f / 100.0, 17.3f / 100.0)); vecVerts.push_back(b2Vec2(-536.0f / 100.0, 18.0f / 100.0)); vecVerts.push_back(b2Vec2(-518.3f / 100.0, 28.6f / 100.0)); vecVerts.push_back(b2Vec2(-282.1f / 100.0, 13.1f / 100.0)); vecVerts.push_back(b2Vec2(-258.1f / 100.0, 27.2f / 100.0)); vecVerts.push_back(b2Vec2(-135.1f / 100.0, 18.7f / 100.0)); vecVerts.push_back(b2Vec2(9.2f / 100.0, -19.4f / 100.0)); vecVerts.push_back(b2Vec2(483.0f / 100.0, -18.7f / 100.0)); vecVerts.push_back(b2Vec2(578.4f / 100.0, 11.0f / 100.0)); vecVerts.push_back(b2Vec2(733.3f / 100.0, -7.4f / 100.0)); vecVerts.push_back(b2Vec2(827.3f / 100.0, -1.1f / 100.0)); vecVerts.push_back(b2Vec2(1006.9f / 100.0, -20.2f / 100.0)); vecVerts.push_back(b2Vec2(1023.2fdddddd / 100.0, -20.2f / 100.0)); i = vecVerts.size(); //I would like to pass this sets of calculations to the stitch method below rather than do it here vector<b2Vec2>::iterator pos; //add y offset value to our b2Vec2 for(pos = vecVerts.begin();pos != vecVerts.end();++pos) { //get b2Vec2 value at index b2Vec2 currVert = *pos; //add y offset (this will come from the sprite image size latterly, set value for testing only b2Vec2 addVert = b2Vec2(currVert.x,currVert.y + 40 /PTM_RATIO); //copy offset added b2Vec2 back to vector as index pos->b2Vec2::operator=(addVert); } //currently using this as kludge to pass my vector to the stitch method b2Vec2 * chain = &vecVerts[0]; [self stitchterrainvertswith:chain num:i];
This is my current method passing in my vector as a C styled array
-(void)stitchterrainvertswith:(b2Vec2 *)verts num:(int)num { //create bodydef b2BodyDef groundBodyDef; //set body as static groundBodyDef.type = b2_staticBody; //set body position groundBodyDef.position.Set(0, 0); //create body using def groundBody = world->CreateBody(&groundBodyDef); //create shapes b2EdgeShape screenEdge; b2ChainShape terrain; terrain.CreateChain(verts, num); groundBody->CreateFixture(&terrain,0); //keeps track of max x value for all the ground pieces that are added to the scene //maxVerts.x += totalXVerts.x; }
I tried using an objc wrapper for std::vector but got kind of lost here is my example:
VecWrap.h #import "Box2D.h" #include <vector> struct VecAcc; @interface VecWrap : NSObject { struct VecAcc* vec; } @end VecWrap.MM #import "VecWrap.h" struct VecAcc { std::vector<b2Vec2>data; }; @implementation VecWrap -(id)init { vec = 0; if (self == [super init]) { vec = new VecAcc; } return self; } -(void)dealloc { delete vec; [super dealloc]; } @end
and then created the following method:
-(void)stitchgroundvectswith:(VecAcc*)vecs num:(int)num;
Which doesn't work is this even possible?
-
coasty over 12 yearsThanks for your help and advice Rob!