dbostream
dbostream

Reputation: 811

Dll import/export

I have inherited a Linux project that I need to port to Windows and Visual Studio. I have setup the same project structure as was the case in Linux but I find the structure a bit strange (maybe it is all good in Linux) and I believe that's what's causing the LNK4217 (locally defined symbol 'symbol' imported in function 'function') and C4273 ('function' : inconsistent DLL linkage) warnings I receive. I would like some advice on how to re-structure the project or change the code to avoid these warnings. Basically this is what I have:

The part that I find strange and what I believe causes the LINK4217 and C4273 warnings is that both the Foo and Bar library contain the header and source file for the class MyClass (the warnings mention this class):

//MyClass.h
class BAR_API MyClass
{
    //Methods etc.
}

Where BAR_API is defined as __declspec(dllexport) in the Bar library while in the Foo library it is __declspec(dllimport) according to:

#ifdef BAR_EXPORTS
#define BAR_API __declspec(dllexport)
#else
#define BAR_API __declspec(dllimport)
#endif

How do you propose I change this? Would it help to move MyClass to its own library and have Foo and Bar include it or change so that BAR_API is defined as nothing instead of __declspec(dllimport) in the Foo library?

Upvotes: 1

Views: 1940

Answers (1)

David Elkind
David Elkind

Reputation: 169

Let's see what you have here 1. Foo.dll that defines MyClass and exports it 2. Bar.dll that depends on Foo.dll, but also defines MyClass - and this is the source of ambiguity that confuses your linker.

The right thing, to my understanding, is to:

  1. Define MyClass in Foo.dll (since Bar.dll already depends on it) and export MyClass using __declspec(dllexport) in Foo.dll's MyClass declaration.
  2. #include header file that declares MyClass (where it will be specified as imported using __declspec(dllimport)) where appropriate in the Bar.dll's .cpp files; however, do not include the .cpp file that implements MyClass.

BAR_API (which in this case should be renamed to FOO_API) helps you achieve this by being defined as either dllexport or dllimport based on whether BAR_EXPORTS (which in this case should be renamed to FOO_EXPORTS) is defined. You should #define FOO_EXPORTS in every source file in the Foo project either by setting compiler command line parameter or by #including common header that #defines FOO_EXPORTS in every .cpp file in the Foo project (but not in the Bar project).

This way both Foo.dll and Bar.dll will use MyClass from the Foo.dll.

HTH

Upvotes: 2

Related Questions