3

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

4 Answers 4

1

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.

Sign up to request clarification or add additional context in comments.

3 Comments

I could, and that would be the easy way. But, that could be a lot of copies that I'd prefer to avoid. You make a good point about the char* pointer, though.
Well, occasionally I write very fast code. From that I know that less than 1% of the codebase is worth optimizing. The rest I do the "easy" way, so I can work harder on the 1%. This could be your 1% but I did not see any numbers how fast it is/should be so I assumed not.
It isn't that this needs to be fast. It's just that I'm hoping for a more elegant method. If I can't find one, that's fine. You might consider this a waste of my time, but if I can find a solution, then I can apply it in the future and make my future code that much better.
1

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.

3 Comments

Hmm... I'm still on daily rep cap from yesterday, oh well.
It's legal C++98 too. Unfortunately, you can't get an array of a different object type without copying.
This is the same as &vec->front() that I'm doing now.
0

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)

3 Comments

Yes, but that puts certain restrictions on the order of objects in the class and their placement. I'd like to avoid that, if possible.
so if you want custom order that create a function converts your object to struct.
Something like the MyClass::GetTable() function that's in the code above?
0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.