Click here to Skip to main content
15,886,519 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
Hi all,
I'm a new member of code project and I'm not an expert software designer, therefore, please, use a simple language for your answers.
Now I'm facing this problem: I have to create a dll which should be used by several clients, using either different compilers or different version of the same compilers (for example Visual Studio 2006 and Visual Studio 2013). My library must contain many class definitions, each of them with its own members and methods. Many class members are std::vector. I want to export only the methods of the main class, you can find the .h of this class (CMsg.h) below:

C++
#include "T_Msg.h"
    
    #ifdef MSG_EXPORTS
    #define MSG_API __declspec(dllexport)
    #else
    #define MSG_API __declspec(dllimport)
    #endif
    
    class MSG_API CMsg
    {
    public:
      CMsg(unsigned char *data, int nLen);
      const std::vector <T_Msg> &ExtractListMsg() {return m_ListMsg;};
    
      CMsg(T_Msg& Msg);
      unsigned char* ExtractBuffer(int& nLen) {nLen = m_WriteBit.LengthByte();return m_WriteBit.DataByte();};
    
      ~CMsg();
    
      void Decode(unsigned char *data, int nLen);
      void Encode(T_Msg& Msg);
    
    private:
    
      std::vector <T_Msg> m_ListMsg;
      CWriteBit m_WriteBit;
    };
    
    #endif // CMsg_H


Can I compile my dll using std::vector as class members and making it portable across different compilers?
Is this the right way? Otherwise, how should I write my classes?
I have found many articles about this problem, but with different suggestions and conclusions (for example for what concerns the use of std::vector). Moreover this articles are often too much complicated and I have a little time to find the right way.
Thank you in advance for your precious answers.
Posted

1 solution

I would advise you to avoid standard library in any exported method because even with the same compiler, the debug and release version of a std::vector can be different.


I have write a complex interface for a project inside my company, it must be compatible with Borland C++ 2009 and VS2010.


To manage this project using the following tips :



  • I create my own template vector to have :

    • same allocate memory method (new/delete/malloc/free are not compiler compatible)
    • same data structure (std::vector do not have same data members in Borland and VS)

  • calling convention forced to __stdcall (by default VS uses __thiscall which put the this pointer in the ecx register and not in the stack)
  • to allow DLL evolution without recompiling the all project, I fixed interface (abstract class without any data members)
  • avoid structure in return type (Borland and VS filled the returned structure differently)

To your class :



  • keep any private data private : do not put them in .h file use class inheritance
  • use basic type to transfert data : to fill (std::vector<t>&) use (T* data, size_t maxItem)

CMsg.h


C++
#include "T_Msg.h"
#ifdef MSG_EXPORTS
#define MSG_API __declspec(dllexport)
#else
#define MSG_API __declspec(dllimport)
#endif
MSG_API IMsg* CreateMsg(unsigned char* data, int nLen);
MSG_API void DeleteMsg(IMsg* msg);
class IMsg
{
protected:
virtual ~IMsg() { }; // will generate error if delete is used on a IMsg*
public:
// All methods are pure virtual (=0)
virtual int __stdcall ExtractListMsg(T_Msg* data, size_t nbMaxItem) = 0;
virtual int __stdcall ExtractBuffer(unsigned char* data, size_t nbMaxLen) = 0;
virtual void __stdcall Decode(unsigned char *data, int nLen) = 0;
virtual void __stdcall Encode(T_Msg& Msg) = 0;
};

CMsg.cpp


C++
...
class CMsg : public IMsg
{
public:
  // Implement the virtual method from IMsg here.
private:
  std::vector<T_Msg> m_ListMsg;
  CWriteBit m_WriteBit;
};
...

I will not write all here, you will have to complete by yourself...

 
Share this answer
 
v2
Comments
Philippe Mori 5-Aug-15 13:27pm    
Well, you can also uses Active/X (COM) for that purpose. However, a lot need to be learn...

Also, you should provide wrapper classes that calls your DLL so that the user would have a friendly interface to use your code. It would add some overhead but can make the code much simpler to use.

That interface would also allows to convert strings to those used by the user compiler... As at the DLL boundary you would use either C style string or BSTR. In any case, you would have to do proper memory managment. A string allocated by one compiler must be released by that same compiler or you must use the OS functions which might be somewhat slower as a compiler typically do suballocation...

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