PaulH
PaulH

Reputation: 7863

turning a std::vector of objects in to an array of structures

I have a VS2008 C++ program where I'm wrapping a C API for use in a C++ program. The C API is expecting an array of TABLE_ENTRY values as shown below.

Other than copying the data from each of the MyClass structures in to a new TABLE_ENTRY structure in MyClassCollection::GetTable(), is there a way to get the functionality I'm looking for?

Thanks, PaulH

struct TABLE_ENTRY {
    const char* description;
    DWORD value;
};

class MyClass
{
public:
    MyClass( const char* desc, DWORD value ) : 
        description( desc ),
        some_value( 1 )
    {
    };

    TABLE_ENTRY* GetTable()
    {
        entry_.description = description.c_str();
        entry_.value = some_value;
        return &entry_;
    };

    TABLE_ENTRY entry_;
    std::string description;
    DWORD some_value;
};

class MyClassCollection
{
public:
    TABLE_ENTRY* GetTable()
    {
        return collection_.front()->GetTable();
    };

    void Add( MyClass* my_class )
    {
        collection_.push_back( my_class );
    }
private:
    std::vector< MyClass* > collection_;
};

int _tmain( int argc, _TCHAR* argv[] )
{
    MyClass class1( "class1", 1 );
    MyClass class2( "class2", 2 );

    MyClassCollection collection;
    collection.Add( &class1 );
    collection.Add( &class2 );

    TABLE_ENTRY* table = collection.GetTable();

    // table is to be used by the C API. Therefore, these next
    // calls should function as shown.
    TABLE_ENTRY entry1 = table[ 0 ]; // should be class1's table (works)
    TABLE_ENTRY entry2 = table[ 1 ]; // should be class2's table (full of junk)

    return 0;
}

Upvotes: 3

Views: 250

Answers (4)

Don Reba
Don Reba

Reputation: 14041

By asking for a TABLE_ENTRY array, the API lets you know that it expects data to be arranged in memory in this specific manner. There is no way of meeting the API's expectations with data arranged any differently, so you are out of luck.

Upvotes: 0

user180326
user180326

Reputation:

I'd go for copying to a vector<TABLE_ENTRY> and pass &entries[0] to the C API.

And, I would not store the TABLE_ENTRYs in your C++ class. I'd only make them just as you call the API, and then throw them away. That's because the TABLE_ENTRY duplicates the object you copy from, and it is storing a direct char* pointer to a string who's memory is managed by a std::string. If you modify the source string (and cause reallocation), you have a dangling pointer.

Upvotes: 1

Andrey
Andrey

Reputation: 60065

if your fields were identical (string != char*) you could cast your object to void* and then cast to structure with some offset (to skip VMT and other OOP stuff)

Upvotes: 0

Tronic
Tronic

Reputation: 10430

To get an array: (this is made legal by C++03, but all C++98 implementations appear to support it too)

&vec[0]

Notice that the vector still owns the contents, so don't delete the memory or realloc it.

Upvotes: 1

Related Questions