1

I must use the C++ OpenVPN3 library to develop a Qt application with OpenVPN capabilities. The problem is that I need to make a class that derives from both QObject and an abstract class provided by this library.

class Client : public QObject, public ClientAPI::OpenVPNClient {
    Q_OBJECT
{
 . . .
}

All of the types I need to use are kept in one big source (cpp) file called ovpncli.cpp. This becomes problematic when I'm now including a source file in a header file, because it causes a multiple definition error when the translation units are generated by the compiler. Classes that inherit from QObject must also have a separate definition and implementation unless you add "include myclass.moc" to the end (but this hasn't worked for me as seen here). The library developers have not said much other than "putting the OpenVPN header files only in my class's implementation file", but this is impossible because the class definition is inheriting from a class defined only in the `ovpnfile.

Is there a way I can include a cpp file in a header file while preventing the multiple definition error at the same time?

Chase
  • 95
  • 11
  • 1
    There is no need to include .cpp anywhere. You should use corresponding `ovpncli.hpp` file instead. – user7860670 May 20 '19 at 17:55
  • @VTT Please refer to the comment I've left on Ben's answer. I would have thought the same thing, but it doesn't work, and according to one of the maintainers you have to use the .cpp file. – Chase May 20 '19 at 17:58
  • Related: https://github.com/OpenVPN/openvpn3/issues/66 – drescherjm May 20 '19 at 20:02
  • @drescherjm I am the one who opened that issue, and frankly, nothing that I didn't already know was said by them, which is why I'm here. OpenVPN headers cannot be entirely excluded from my class's header file, otherwise it can't inherit from ClientAPI::OpenVPNClient. – Chase May 20 '19 at 20:08
  • 1
    You may have to switch to composition instead of inheritance if you can't get around this bad design. – drescherjm May 20 '19 at 20:09
  • @drescherjm It's truly frustrating that the entire library doesn't separate the classes into separate header and implementation files. That and the fact that there is no other way to make an OpenVPN GUI client using Qt without using process calls instead of having the protocol implemented in the application :/ – Chase May 20 '19 at 20:13
  • "the fact that there is no other way to make an OpenVPN GUI client using Qt" is not a fact at all. Whatever OpenVPN functions this convenience wrapper is called, you can call directly bypassing the brokenness. Of course that would be a lot less convenient. – Ben Voigt May 20 '19 at 23:56
  • @BenVoigt I don't see how I'd be able to implement the functionality of an OpenVPN client in Qt without writing my own, seeing as how it's the only C++ implementation available. I ended up using containment by creating a wrapper for the wrapper (ouch) and then forward declaring the Client class and storing a pointer to an instance of it. It seems to be working right now. – Chase May 21 '19 at 00:43

1 Answers1

3

The definition of that class is in ovpncli.hpp not ovpncli.cpp. (Yes, really) So just use the header system the way it was intended.

#include "ovpncli.hpp"

and link with ovpncli.cpp but do not #include it.

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
  • According to https://github.com/OpenVPN/openvpn3/issues/48#issuecomment-398754706, "you **must** use `ovpncli.cpp`". I've also tried this and just gotten more errors. – Chase May 20 '19 at 17:54
  • @Chase I bet you've got "undefined reference/unresolved external symbol" errors and instead of looking up the appropriate question created this one which is basically an XY problem. Note that "must use ovpncli.cpp" does not imply "must include ovpncli.cpp" – user7860670 May 20 '19 at 17:57
  • @Chase: The other user whose thread you linked to was missing the **and link with ovpncli.cpp** step. They include'd ovpncli.hpp as a header and did absolutely nothing with ovpncli.cpp – Ben Voigt May 20 '19 at 17:58
  • @VTT Trust me, I have looked up how to resolve the compiler error many times. – Chase May 20 '19 at 17:59
  • 1
    @Chase The thread you linked HAS NO COMPILE ERROR. [This is a linking error](https://pastebin.com/sBXLXcE1) And while the linker input list is hidden inside a *.jom file which is not included in the pastebin, I'm 100% sure that the problem is failing to compile ovpncli.cpp as a separate unit and then pass ovpncli.obj to the linker. – Ben Voigt May 20 '19 at 18:01
  • @VTT Here is what happens when I include ovpncli.hpp in the header file and add ovpncli.cpp to my Qt project file's SOURCES variable: https://pastebin.com/xrQExuwi – Chase May 20 '19 at 18:18
  • 1
    @Chase: Try `#include ` before `#include "ovpncli.hpp"` – Ben Voigt May 20 '19 at 18:22
  • @BenVoigt Unfortunately that did not resolve my issue. I am receiving a lot of "not declared in this scope", mostly from OPENVPN_LOG macros. If I replace ovpncli.hpp with .cpp out of curiosity while still having ovpncli.cpp as a source file of the project, I get a multiple definition error, yet having it present only once will cause complaints about lack of definition. – Chase May 20 '19 at 18:27
  • @Chase: Well, the [`ovpncli.cpp` includes one file, `openvpn/io/io.hpp`](https://github.com/OpenVPN/openvpn3/blob/master/client/ovpncli.cpp#L30) before including its own header file. So try including that one. By this time, though, I'd be having second thoughts about using that particular convenience wrapper, especially for something as important as crypto. – Ben Voigt May 20 '19 at 18:41
  • @BenVoigt I've tried, but I'm receiving more multiple definition errors. Here is an example of my issue that I've isolated in a Qt project: https://www.sendspace.com/file/fy92d4 – Chase May 20 '19 at 19:12
  • Additionally, if I uncomment all of the #includes from initprocess.hpp to selftest.hpp with the exception of cliopthelper.hpp, I get 3 errors - incomplete type errors. If I then go to uncomment merge.hpp I receive all of the multiple deifnition errors. – Chase May 20 '19 at 19:49
  • @Chase Can you give an example of a multiple definition error you get when including just `ovpncli.hpp` and not the cpp file? – Ben Voigt May 20 '19 at 23:57