ppescher / resizablelib

A set of MFC classes to easily make resizable windows
Other
55 stars 27 forks source link

Inline functions problem with AFX_EXT_CLASS #17

Open 0ric1 opened 4 years ago

0ric1 commented 4 years ago

I want to create a dynamic Resizable library .dll instead of the static Resizable library .lib and want to use AFX_EXT_CLASS to make the task simple, but get error LNK2005 ... already defined in ... / fatal error LNK1169: one or more multiply defined symbols found. Is it possible to move some inline functions e.g. CResizableDialog::GetResizableWnd and all CResizableLayout::AddAnchor / AddAllOtherAnchors / RemoveAnchor from the header to the cpp file?

ppescher commented 4 years ago

I guess inline functions should not go into the DLL, but stay in the header file, just like they do not end up in the compiled LIB file.

0ric1 commented 4 years ago

Inline function from a dll get expanded into the application code and could also cause version conflicts, see https://docs.microsoft.com/en-us/cpp/build/exporting-and-importing-using-afx-ext-class?view=vs-2019

0ric1 commented 4 years ago

Also see https://docs.microsoft.com/en-us/cpp/cpp/defining-inline-cpp-functions-with-dllexport-and-dllimport?view=vs-2019 and https://devblogs.microsoft.com/oldnewthing/20140109-00/?p=2123.

ppescher commented 4 years ago

Of course all the functions could be moved from the header to the source file and not inlined. They are not that way simply because I did not mean to have a DLL initially. Given the power of modern CPUs it probably doesn't matter anymore. Maybe it did not matter performance-wise also in year 2000 when I first started this project. ;-)

irwir commented 4 years ago

Speaking about inlining.

  1. In some cases VC++ compiler optimizes by inlining; though it could be known only afterwards.
  2. There is a possibility to use macro and add dll/inline specifiers depending on the kind of build.
0ric1 commented 4 years ago

I guess inline functions should not go into the DLL, but stay in the header file, just like they do not end up in the compiled LIB file.

You can create a little example and use dumpbin to see that a function is also exported from the dll.

  1. There is a difference between normal and __declspec(dll{im|ex}port) inline functions, I recommend reading https://devblogs.microsoft.com/oldnewthing/20140109-00/?p=2123
irwir commented 4 years ago

My previous message was too short and thus unclear.

Definition in .cpp might be inlined by compiler without inline keyword, but may be not. Methods defined in header files are inline by default. The idea is to avoid mixing 'inline' and 'export' properties, and make these mutually exclusive. That is, move definition to .cpp module, and add inline/export depending on the kind of build by means of a simple macro.

0ric1 commented 4 years ago

The Idea is to use AFX_EXT_CLASS to export the whole classs because you must be able to derive from them and we need the macros DYNAMICDECLARE... so all class member functions are exported too.

irwir commented 4 years ago

The Idea is to use AFX_EXT_CLASS to export the whole classs

In non-dll builds AFX_EXT_CLASS is defined as an empty string. You can create a macro that would add inline specifier to the methods that had to be moved from headers to .cpp files. Then for static libraries compiler should generate the same code with inlining - as in the current version.

ppescher commented 4 years ago

I guess I don't get it ... how can the compiler inline functions that are defined in another compilation unit? Even if I use the inline keyword, shouldn't the function definition be in the header file?

irwir commented 4 years ago

C++ Standards tells that a function defined inside a class definition is inline. It is possible to declare an inline function, and define it elsewhere. Also there could be more than one definition:

An inline function or variable shall be defined in every translation unit in which it is odr-used and shall have exactly the same definition in every case