How to create a module definition file for C++ classes

Dear Bertrand,

For testing purposes I have created libraries “MyClass.dll” and “libMyClassIOMT.dll” whereby library “MyClass.dll” uses class “MyClassIO” which
is defined in library “libMyClassIOMT.dll”.

class MyClassIO
{
private:
   const char *fString;

public:
   MyClassIO();
   virtual ~MyClassIO();
   virtual void ReadFileC(const char *infile);
   virtual void ReadFileCpp(const char *infile);
   virtual void WriteFileC(const char *outfile);
   virtual void WriteFileCpp(const char *outfile);
   virtual void ReadIFileStream(ifstream &input);
   virtual void WriteOFileStream(ofstream &output);
};

The problem is that I need to create a module definition file for library “libMyClassIOMT.dll” so that library “MyClass.dll” can use class “MyClassIO”.
Since my efforts to create “libMyClassIOMT.def” manually failed I tried to use “dumpbin”, see: msdn.microsoft.com/en-us/library/20y05bd5.aspx

dumpbin /EXPORTS /OUT:tmp.txt libMyClassIOMT.lib

Thus my final module definition file “libMyClassIOMT.def” looks as follows:

LIBRARY libMyClassIOMT
EXPORTS
   ??0MyClassIO@@QAE@ABV0@@Z (public: __thiscall MyClassIO::MyClassIO(class MyClassIO const &))
   ??0MyClassIO@@QAE@XZ (public: __thiscall MyClassIO::MyClassIO(void))
   ??1MyClassIO@@UAE@XZ (public: virtual __thiscall MyClassIO::~MyClassIO(void))
   ??4MyClassIO@@QAEAAV0@ABV0@@Z (public: class MyClassIO & __thiscall MyClassIO::operator=(class MyClassIO const &))
   ??_7MyClassIO@@6B@ (const MyClassIO::`vftable')
   ?ReadFileC@MyClassIO@@UAEXPBD@Z (public: virtual void __thiscall MyClassIO::ReadFileC(char const *))
   ?ReadFileCpp@MyClassIO@@UAEXPBD@Z (public: virtual void __thiscall MyClassIO::ReadFileCpp(char const *))
   ?ReadIFileStream@MyClassIO@@UAEXAAV?$basic_ifstream@DU?$char_traits@D@std@@@std@@@Z (public: virtual void __thiscall MyClassIO::ReadIFileStream(class std::basic_ifstream<char,struct std::char_traits<char> > &))
   ?WriteFileC@MyClassIO@@UAEXPBD@Z (public: virtual void __thiscall MyClassIO::WriteFileC(char const *))
   ?WriteFileCpp@MyClassIO@@UAEXPBD@Z (public: virtual void __thiscall MyClassIO::WriteFileCpp(char const *))
   ?WriteOFileStream@MyClassIO@@UAEXAAV?$basic_ofstream@DU?$char_traits@D@std@@@std@@@Z (public: virtual void __thiscall MyClassIO::WriteOFileStream(class std::basic_ofstream<char,struct std::char_traits<char> > &))

Sadly using this module definition file with the linker results in the following error:

        "C:\Programme\Microsoft Visual Studio 9.0\VC\bin/link" /dll /def:libMyClassIOMT.def /out:libMyClassIOMT.dll fp10.obj *.obj
Microsoft (R) Incremental Linker Version 9.00.21022.08
Copyright (C) Microsoft Corporation.  All rights reserved.

libMyClassIOMT.def(3) : fatal error LNK1118: syntax error in '(public:' statement
NMAKE : fatal error U1077: '"C:\Programme\Microsoft Visual Studio 9.0\VC\bin/link.EXE"' : return code '0x45e'
Stop.

Then I tried to use “pexports.exe” to create a module definition file but got the following message:

C:\home\Rabbitus\CRAN\MyClassIO\bin>pexports libMyClassIOMT.dll > libMyClassIOMT.exp
pexports: libMyClassIOMT.dll: could not load PE image

Since I am not able to create a module definition file I am currently using the following option when defining class “MyClassIO”:

#define DllExport   __declspec( dllexport ) 

class DllExport MyClassIO
{
private:
   const char *fString;

public:
   MyClassIO();
   virtual ~MyClassIO();
   virtual void ReadFileC(const char *infile);
   virtual void ReadFileCpp(const char *infile);
   virtual void WriteFileC(const char *outfile);
   virtual void WriteFileCpp(const char *outfile);
   virtual void ReadIFileStream(ifstream &input);
   virtual void WriteOFileStream(ofstream &output);
};

Although this option works perfectly fine on WinXP, i.e. library “MyClass.dll” can call “libMyClassIOMT.dll”, this is not a solution since the
code for the class definition is VC++ specific. Thus I have the following questions:
1, How do I create a correct module definition file for class “MyClassIO”?
2, How does ROOT handle this case? (Obviously ROOT does not use DllExport)

For your information I am attaching the complete source code for library “libMyClassIO”.

Best regards
Christian
MyClassIO.tar.gz (93.2 KB)

Hi Christian,

You can use bindexplib.exe, which is available in ROOT/bin. Here is what would be the syntax for your case:

And then add these linker options:

It should work. You can also take a look in $ROOTSYS/test/Makefile and $ROOTSYS/test/Makefile.win32 (note the syntax is slightly different)

Cheers, Bertrand.

Dear Bertrand,

Thank you very much for your help, this worked perfectly.

I have only one minor question: How do other Windows developers, who do not have access to ROOT, solve this problem?

Best regards
Christian

Hi Christian,

One option is to write the.def file by hand, another one is to use __declspec( dllexport )…
Usually Windows developers know how to do it right :wink:

Cheers, Bertrand.

[quote=“cstrato”]I have only one minor question: How do other Windows developers, who do not have access to ROOT, solve this problem?[/quote]Windows developer has no this problem. "__declspec( dllexport )… " is the part of VC++ language and they are tought to define the DLL entry points in the source code. There is the historic reason. Once upon a time at the age of Intel86 CPU with 640Kb of main memory and 16-bits address space one can not afford to export all symbols.