Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
309 views
in Technique[技术] by (71.8m points)

.net - How to make consistent dll binaries across VS versions?

For instance, winsock libs works great across all versions of the visual studio. But I am having real trouble to provide a consistent binary across all the versions. The dll compiled with VS 2005 won't work when linked to an application written in 2008. I upgraded both 2k5 and 2k8 to SP1, but the results haven't changed much. It works some what ok. But when they include this with a C# app, the C# app gets access violation errors, but with classic C++ application it works fine.

Is there a strategy that I should know when I provide dlls ?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

First, dont pass anything other than plain old data accross DLL boundries. i.e. structs are fine. classes are not. Second, make sure that ownership is not transferred - i.e. any structs passed accross the dll boundry are never deallocated outside the dll. So, if you dll exports a X* GetX() function, there is a corresponding FreeX(X*) type function ensuring that the same runtime that allocated is responsible for de-allocation.

Next: Get your DLLs to link to the static runtime. Putting together a project comprimising dls from several 3rd parties, each linked to and expecting different runtimes, potentially different to the runtime expected by the app, is a pain, potentially forcing the installer software to install runtimes for 7.0, 7.1, 8.0 and 9.0 - several of which exist in different service packs which may or may not cause issues. Be kind - statically link your dll projects.

-- Edit: You cannot export a c++ class directly with this approach. Sharing class definitions between modules means you MUST have a homogeneous runtime environment as different compilers or versions of compilers will generate decorated names differently.

You can bypass this restriction by exporting your class instead as a COM style interface... which is to say, while you cannot export a class in a runtime independent way, you CAN export an "interface", which you can easilly make by declaring a class containing only pure virtual functions...

  struct IExportedMethods {
    virtual long __stdcall AMethod(void)=0;
  };
  // with the win32 macros:
  interface IExportedMethods {
    STDMETHOD_(long,AMethod)(THIS)PURE;
  };

In your class definition, you inherit from this interface:

  class CMyObject: public IExportedMethods { ...

You can export interfaces like this by making C factory methods:

  extern "C" __declspec(dllexport) IExportedClass* WINAPI CreateMyExportedObject(){
    return new CMyObject; 
  }

This is a very lightweight way of exporting compiler version and runtime independent class versions. Note that you still cannot delete one of these. You Must include a release function as a member of the dll or the interface. As a member of the interface it could look like this:

  interface IExportedMethods {
    STDMETHOD_(void) Release(THIS) PURE; };
  class CMyObject : public IExportedMethods {
    STDMETHODIMP_(void) Release(){
      delete this;
    }
  };

You can take this idea and run further with it - inherit your interface from IUnknown, implement ref counted AddRef and Release methods as well as the ability to QueryInterface for v2 interfaces or other features. And finally, use DllCreateClassObject as the means to create your object and get the necessary COM registration going. All this is optional however, you can easilly get away with a simple interface definition accessed through a C function.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...