std :: vector в объективном методе c - PullRequest
4 голосов
/ 03 января 2012

Я работаю в цели C ++.Проблема, с которой я застрял, заключается в том, что мне нужно передать std :: vector в объектный метод c.Это возможно?Ниже приведен мой текущий код, где я должен выполнить свои вычисления для вектора в методе определения вектора (добавив значение смещения к членам массива), прежде чем перейти к методу в виде массива C.В идеале я хотел бы установить значения смещения во втором методе, разделив таким образом определение (их будет несколько). Смещение будет переменным, в отличие от приведенного ниже примера.

Поэтому вместо передачи (b2Vec2 *) vect я хочу использовать векторы

- (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];

Это мой текущий метод, передающий мой вектор в виде массива в стиле C

-(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;
    }

Я попытался использовать оболочку objc для std:: vector, но я потерял вид, вот мой пример:

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

, а затем создал следующий метод:

-(void)stitchgroundvectswith:(VecAcc*)vecs num:(int)num;

Что не работает, это вообще возможно?

Ответы [ 4 ]

7 голосов
/ 03 января 2012

Все правильно, и решение Барри Уорка работает, но я не рекомендую его, потому что подобные уловки препроцессора для конкретного языка - это хрупкая IMO.В частности, они не работают правильно, если задействованы пространства имен, и работают только с указателями.

Во-первых, я настоятельно рекомендую разработчикам максимально разделить ObjC и C ++ и минимизировать ObjC ++ до нескольких.места, где это действительно нужно.ObjC ++ - это сумасшедший язык, с которым GDB часто сталкивается с проблемами, ухудшает производительность ARC, медленнее компилируется и, как правило, полезен на время, а не настоящий язык.

Я рекомендую этот подход, чтобы скрыть ваш C ++методы из ObjC в заголовках:

@interface MyClass

- (void)anOtherMethodCalledFromObjC;

#ifdef __cplusplus
- (void)stitchGroundVectsWithVector:(std::vector<b2Vec2>)vec;
#endif
@end

Но, вообще говоря, я рекомендую, чтобы большинство ваших программ были файлами .m и .cpp, с несколькими файлами .mm для их склеивания.

Для подробного обсуждения того, как сделать это в старом коде, см. Wrapping C ++ - Take 2 .Более новый код не требует, чтобы ivars находился в заголовках, поэтому его должно быть еще проще реализовать сегодня.

3 голосов
/ 03 января 2012

Вам не нужно писать обертки.В этом цель Objective-C ++: вы можете объявить метод Obj-C для приема / возврата объекта C ++, и он будет работать.Например:

- (void)someMethod:(const std::vector<b2Vec2>&)vec {
    /* do something with vec in C++ code */
}
2 голосов
/ 03 января 2012

Как указывают @ H2CO3 и @ Джошуа Вайнберг, Objective-C ++ позволяет вам определять метод с аргументом типа std::vector (или его ссылкой и т. Д.).Это будет хорошо работать, если вы остаетесь в Objective-C ++ для всех файлов, которые содержат соответствующий .h.Однако если вам необходимо импортировать этот заголовок в файлы, скомпилированные в Objective-C, вам нужно будет передать указатель и скрыть тип из кода Objective-C:

#ifdef CPLUSPLUS
typedef std::vector* vecp_t
#else
typedef void* vecp_t
#endif

@interface MyClass
{}

- (void)anOtherMethodCalledFromObjC;
- (void)stitchGroundVectsWithVector:(vecp_t)vec;
@end

(позволил Objective-C стилизовать имена ваших методов)

1 голос
/ 03 января 2012

В Objective-C ++ нет причины, по которой вы не можете просто определить stichgroundvectswith: как -(void)stitchgroundvectswith:(std::vector<bVect2>&)vets num:(int)num, как если бы вы работали в прямом C ++. В этом режиме объекты C ++ могут быть бесшовно (с некоторыми оговорками) интегрированы в методы Obj-C.

...