Click here to Skip to main content
15,915,603 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hi,
I have DLL which i am using is i have created. which will talk to webservice and get some details. there are almost 80 API's i have created depending on webservice. all works fine except for one which returns vector elements. my DLL is pure c++ cod compile with msvc2008 in Qt.
i was checking through Qt application but since it was platform independent DLL it was necessary to check with Visual studio Application. here i encounter with issue.
when i call API from Qt App function returns with proper Vector elements. but same code when tried from MFC App does not return element with some values but do not show list in vector.
i got post in case of using vector in MFC. is there any serialize kind of class require in MFC to populate out Values ?
i did not find any serialize class for vector in MFC on net..
Posted
Comments
beginnergSOAP 13-Apr-12 7:44am    
hi,

here i tried same code with VC 2005 and it works...fine...i am getting List.

pList = [5](0x02bb4ce0 {num=0 name=0x10275e00 "test" },0x02bb4d68 {num=1 name=0x10275e00 "test" },0x02bb4df8 {num=2 name=0x10275e00 "test" },...) // VC2005

pList = 0x0208FF58[3440637000](...,...) // VC2010

is there any problem with setting in VC2010?...since i have not used Visual studio much i really can not guess what setting might be...but i could guess some setting issue...i dont know if i am on right track...can any one give some more information.

I've returned vectors (and other STL types) across DLL/shared library boundaries loads of times and not had a problem. EXCEPT when compiler settings were a lot different OR the DLL was compiled with another compiler in which case all bets are off.

As I found your code in the comment a bit hard to parse this might (CAVEAT, code completly untested, normally I don't do this but I'm using a computer without MFC on it [1]) be workable as a way of serialising a vector into an archive:

template<typename type_to_store>
CArchive &operator<<(
        CArchive &archive,   
        const std::vector<type_to_store> &to_store )
{
    typedef std::vector<type_to_store>::const_iterator iterator;
    for(iterator iter = to_store.begin(); iter != to_store.end(); ++iter )
        archive << *iter;

    return archive;
}


Hopefully any compiler errors should be easy to sort out. If that doesn't work with both applications then you've got two apps that have used significantly different compiler settings to build and the only way around it is to try and work out how to converge them.

Cheers,

Ash

[1] I've only got VC++2010 express which doesn't come with MFC.

Added guff (16/04/12)

It sounds like your problem is that no guarantee that generally you can link C++ code that's compiled with two different compilers. Sometimes you can get away with it especially if you only pass pure (no implementation code or abstract) interface classes - i.e. all the code for the class is either in the DLL or it's in the calling EXE.

If it's not then the binary layout of the object can be different on either side of the EXE/DLL boundary as different compilers compile the same code in different ways AND the vendor might have changed the implementation of the class. MS have had to maul their standard library a fair bit to make it comply to the C++11 standard between VC++2008 and 2010. Where the code compiled with 2010 expects to find the vector's data pointer the code compiled with 2008 compiler might have stuck the size at the same address, the implementations swapping the data members around for some reason them around for some reason.

So, what can you do about this then?

The first thing you can try is pass an abstract class that contains a vector<whatever> and exports a couple of pointers to the start and end of the vector.

An interface like:

C++
class vector_int_marshaller
{
    public:
        virtual int *start_of_vector() const = 0;
        virtual int *end_of_vector() const = 0;
};


And implement it on the DLL (VC++2005) side:

C++
class vector_int_marshaller_imp : public vector_int_marshaller
{
    public:
        vector_int_marshaller_imp( const std::vector<int> &to_marshal ) : to_marshal_( to_marshal )
        {
        }

        virtual int *start_of_vector() const
        {
            return &to_marshal_[0];
        }

        virtual int *end_of_vector() const
        {
            return start_of_vector + to_marshal_.size();
        }

    private:
        const std::vector<int> &to_marshal_;
};


And finally convert it into a VC++2010 vector in the EXE:

C++
std::vector<int> data( vec->start_of_vector(), vec->end_of_vector() );


You can get away with this as you're only using built in types AND a v_table, which MS have to keep in a certain format as they still support COM (ho, ho, ho :-) ).

Having said all that the best thing to do is grab every bit of C++ code you use and compile it with the same compiler. Absolutely everything that doesn't have a pure C interface.

Hope the additions help, I missed the point that you were building with multiple compilers before,

Ash

Edit: Corrected a few typos and unclear bits of text

EditII: Punctuation fail, rewrote a chunk of it to try and make it clearer. grr...

Edit III: Just noticed some stray guff the editor left lying around
 
Share this answer
 
v7
Comments
beginnergSOAP 16-Apr-12 3:42am    
Yes i do have problem with Compiler setting as same code gives me List in VC2005 as below:

pList = [5](0x02bb4ce0 {num=0 name=0x10275e00 "test" },0x02bb4d68 {num=1 name=0x10275e00 "test" },0x02bb4df8 {num=2 name=0x10275e00 "test" },...) // VC2005
But VC2010 gives following
pList = 0x0208FF58[3440637000](...,...) // VC2010
my DLL is compiled in QT MSVC2008, pure C++ code..all API works fine except API which return Vector in VC2010 , work fine in VC2005.
i can not guess setting issue however i overlook Project setting in both 2005 and 2010. any guess...
Aescleal 16-Apr-12 5:04am    
Ah ha!

Amended my answer above.

Cheers,

Ash
beginnergSOAP 16-Apr-12 8:07am    
Hi,

My DLL is in QT (MSVC2008 Compiler) pure C++ code, all code is in DLL. from Application i am just calling API 2 lines of code. since project is platform independent (DLL), Qt DLL in Qt Application works fine. i have tried Qt DLL in Visual Studio 2010. i was not getting list as said above. i then tried in VC-2005 and it works. since i am new to VS, i really could not get exact problem however i could figure out some setting issue.
i read ur solution but not got why to use VC-2005 and then VC-2010. i have to use VC- 2010. as have to release project with VC- 2010. VC-2005 i used for testing vector issue since did not worked in VC -2010.
Aescleal 16-Apr-12 9:14am    
So the API you've implemented in your Qt based DLL NEVER returns any objects or takes any objects as parameters? If any of DLL functions takes (FREX) a std::vector<> or returns one then you might end up with the sort of binary layout problem I mentioned above.
beginnergSOAP 17-Apr-12 0:03am    
no the thing is all API is working fine when i have tried from MFC application , only API which returns vector gives me problem in VC2010. not in VC2005.
i tried every possible way all giving me same issue. i am giving exactly same code as test which represent my entire project code. it divides in to two 1. DLL 2. App using DLL.

//Below code is in My DLL Source and Header accordingly DLL compiled in QT (MSVC2008)plain C++ code.
view source
print?
01 //This is mt Template Class
02 template <class t="">
03 class STDList
04 {
05 public:
06 std::vector<t> pList;
07
08 public:
09
10 int Count()
11 {
12 return pList.size();
13 }
14
15 T at(long index)
16 {
17 return pList[index]; // pList.at(index), i have Try
18 }
19
20 void add(T item)
21 {
22 pList.push_back(item);
23 }
24 };
25
26 class VtestList: public STDList<vtest*>{};
27
28 class __declspec(dllexport) Vtest
29 {
30 public:
31 int num;
32 char* name;
33 };
34
35 class __declspec(dllexport) TestClass
36 {
37 public:
38
39 std::vector<vtest>* func1(void);
40 }
41
42 VtestList* TestClass::func1(void)
43 {
44 VtestList* testing = new VtestList();
45
46 for (int i = 0; i < 5; i++)
47 {
48 Vtest* ptest = new Vtest();
49 ptest->num = i;
50 ptest->name = "Test";
51 testing->add(ptest);
52 }
53 return testing;
54 }

// Below is Application code very simple 2 lines, Application both in QT and MFC. include LIB, DLL and header file.
1 TestClass* objTest = new TestClass();
2 VtestList* RetVect = objTest->func1();



above code i tried with template class and with out template class in DLL and also with std::vector<vtest*>* and other way, all ways gives me same problem in MFC(2010) when i tried to see content of "RetVect" it gives "RetVect->pList = 0x0208FF58[3440637000](...,...)" with or with out template i am getting same big number for vector some thing like [3440637000].
this behavior is only in VC2010 when i use DLL, not in Qt Application nor in VC2005. instead of STD::vector i tried STD::List same issue with VC2010.
For N-reasons, it is not safe to pass Standard template library objects across modules. They just wont hold and break between module boundaries.

The alternative is the break them up into classes and pass around
 
Share this answer
 
Comments
beginnergSOAP 31-Mar-12 9:08am    
is there no solution as i had used below code for try:
template<typename t="">
CArchive& STORE_VECTOR(CArchive& ar, const std::vector<t>& t_vector)
{
ar << to_store.size();
end = t_vector.end(); // i am getting one element from vector
for(std::vector<t>::size_type i = 0; i < t_vector.size(); i++
ar << t_vector[i];
return ar;
}
at end = t_vector.end(); line i am getting only one element from t_vector (if suppose 3 elements are present in vector) not end one but 1st one. like if
size_type size() const
{ // return length of sequence
return (_Mylast - _Myfirst);
}
_Mylast shows 1 element which is actually 1st element.
_Myfirst shows junck values. this i am getting only inside function not outside if i try to access.
this behavior also very weird and i really can not understand.
at this point i can not changes inside DLL as it is very huge. but since i was getting one element it was sure MFC app. must be getting values. may be i am missing the way of accessing, way of accessing may be differs in MFC.
beginnergSOAP 4-Apr-12 1:50am    
No solution for issue?
JackDingler 13-Apr-12 17:52pm    
I'm not sure exactly what your getting to with your code example.

But the .end() method doesn't return a loc to a valid data. It's used to detect when an iterator has gone past the end of the list.

Further std::vector is not an MFC class. It's part of the ANSI standard and does not come with serialization support for the MFC library.

What you might do is return the size and the address of the first element. The data is guaranteed to be contiguous in memory. So you can access it as a primitive array.
Aescleal 14-Apr-12 6:00am    
The whole "it's not safe" thing isn't particularly true. You can chuck vectors around but you have to make sure that you're using the similar enough compiler settings on both sides of the fence so that the objects look the same when they cross over.

Cheers,

Ash
My answer was in my question only, problem is with Compiler Compatibility.
Nokia has release Qt 4.8.1 on April 11 which comes with msvc2010 Compiler, i was not knowing about their recent release, so now have compiled my DLL in msvc2010 Compiler in Qt and it works fine in VC2010 MFC.
Thax for help.
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900