dcsimg
CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 15 of 15

Thread: Exporting Classes The Right Way, Tricks and Tips?

  1. #1
    Join Date
    Jul 2017
    Posts
    76

    Exporting Classes The Right Way, Tricks and Tips?

    So, after a long time of asking you for advises about dlls, I've reached to a conclusion on how to do stuff and I would like to show it to you and tell me if it's correct.

    First of all let's start with the easy stuff. C++ interfaces, doesn't even need to be exported as dlls since all the implementation is getting handle by the client. Your library just need to define that interface inside a header file, and the client the only thing he need's to do is to include that header file, inherit that interface and implement the abstract methods.

    Now let's talk about classes which are not getting inherited by the client. People here told me that the best way is to create a C factory function that generates an instance of that class. I understand how this works but what about the Methods? Do I have to create a C function wrapper for each method of that class and export these functions into the dll? Consider the code below:

    MyClass.h
    Code:
    class MyClass
    {
    	public:
    		MyClass();
    		~MyClass();
    		void PrintHi();
    };
    MyClass.cpp
    Code:
    #include "MyClass.h"
    #include <iostream>
    
    MyClass::MyClass(){}
    MyClass::~MyClass(){}
    void MyClass::PrintHi(){ std::cout << "Hi!" << std::endl; }
    
    extern "C"
    {
    	__declspec(dllexport) MyClass *CreateMyClass()
    	{
    		return new MyClass();
    	}
    	
    	__declspec(dllexport) void DeleteMyClass(MyClass *obj)
    	{
    		delete obj;
    	}
    	
    	__declspec(dllexport) void PrintHi(MyClass *obj)
    	{
    		obj->PrintHi();
    	}
    }
    So, do I need to create a C wrapper for each Method? Because I tried to only create a factory function (CreateMyClass) and on the client side every time I was using myObj->PrintHi() the compiler was saying "Undefined reference to PrintHi()" and this make sense since I did not export that Method into the dll. This C wrappers will probably work but I'm loosing the C++ way of using a class. And what if I want to inherit that class? How is the constructor of the base class is going to get called since i haven't exported it? As you can see I'm losing all the good object oriented stuff C++ give's me when using C wrappers.

    I thought this carefully and I noticed that every C++ library I used until know (And because I'm a graphics programmer I use a lot of libraries) all of them where only header libraries. Is this a coincidence? Maybe dlls are the reason? You can't export classes into dlls which are going to be compatible with all the compilers out there but what you can do is actually write the whole implementation of you library into header files and let the client include these headers and compile them easily by himself. Is this a good practice to do when creating libraries in c++, since exporting classes into dlls should be a NO for compatibility reasons?

    And then I also thought about precompiled libraries. Why not creating my whole library into header files only and then create a pch.h file that includes all of the necessary files and let the client include that pch.h file, compile it the first time only and use it as a precompiled library. Fast, easy to compile and has compatibility.

    So what do you thing? Have I understand everything correctly? Do you have any better ideas?
    Thank you!

  2. #2
    Join Date
    Feb 2017
    Posts
    370

    Re: Exporting Classes The Right Way, Tricks and Tips?

    Quote Originally Posted by babaliaris View Post
    Why not creating my whole library into header files only
    Yes why not?

    I'd say it's a trend today to distribute libraries by making the library source code available as a set of include files. The users aren't even required to build a compiled version of the library. They just start including the include files of interest into their source code. This is for example how most libraries in the Boost library collection are distributed. These kind of libraries are sometimes called header libraries. In practical terms it means the whole library is on .h files. It's possible because the traditional separation of C++ source code into .h and .cpp files is a convention only and not something C++ demands.

    These are your options to distribute a library:

    1. Either by way of source code, or compiled code (with include files holding declarations).

    2. If it's source code the user either uses it as a pure header library, or is required to build a compiled version of the library before use.

    3. A library in compiled form (regardless of who compiled it) must be linked. There are three ways (of which at least one must be supported by the library provider): static linking, dynamic linking (dll) and dynamic loading (also dll but application controlled).
    Last edited by wolle; December 2nd, 2018 at 04:24 AM.

  3. #3
    2kaud's Avatar
    2kaud is online now Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    6,509

    Re: Exporting Classes The Right Way, Tricks and Tips?

    I thought this carefully and I noticed that every C++ library I used until know (And because I'm a graphics programmer I use a lot of libraries) all of them where only header libraries. Is this a coincidence?
    No! You're just starting to feel the pain of c++ and .dll Unless there is a very good reason, it's much better to have your c++ library code in a header file(s).
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++17 Compiler: Microsoft VS2017 (15.9.3)

  4. #4
    Join Date
    Jul 2017
    Posts
    76

    Re: Exporting Classes The Right Way, Tricks and Tips?

    Then I will stick with this way and of course I'll follow 2klaud's advice to treat c++ as a completely different language ( I'm coming from c)

  5. #5
    Join Date
    Feb 2017
    Posts
    370

    Re: Exporting Classes The Right Way, Tricks and Tips?

    If you plan to distribute your library as a pure header library then there are three basic rules to follow:

    1. Each file must have an include guard.
    2. Free functions must be declared inline.
    3. Use a library specific namespace.

  6. #6
    Join Date
    Jul 2017
    Posts
    76

    Re: Exporting Classes The Right Way, Tricks and Tips?

    Quote Originally Posted by wolle View Post
    If you plan to distribute your library as a pure header library then there are three basic rules to follow:

    1. Each file must have an include guard.
    2. Free functions must be declared inline.
    3. Use a library specific namespace.
    I always use 1,3 but number 2 by free you mean destructor-like functions (which they free objects?). If yes, why I should declare them as inline?

  7. #7
    2kaud's Avatar
    2kaud is online now Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    6,509

    Re: Exporting Classes The Right Way, Tricks and Tips?

    2. Functions defined outside of a class definition in a header file need to be declared as inline so that if the header is included in multiple compilation units you don't get an error referring to already defined functions (I've forgotten the exact error message). See https://en.cppreference.com/w/cpp/language/inline (see description 1) ).
    Last edited by 2kaud; December 2nd, 2018 at 11:59 AM.
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++17 Compiler: Microsoft VS2017 (15.9.3)

  8. #8
    Join Date
    Jul 2017
    Posts
    76

    Re: Exporting Classes The Right Way, Tricks and Tips?

    Quote Originally Posted by 2kaud View Post
    2. Functions defined outside of a class definition in a header file need to be declared as inline so that if the header is included in multiple compilation units you don't get an error referring to already defined functions (I've forgotten the exact error message). See https://en.cppreference.com/w/cpp/language/inline (see description 1) ).
    Oh, I understand what you mean. I didn't know that.
    Last edited by 2kaud; December 2nd, 2018 at 11:59 AM.

  9. #9
    Arjay's Avatar
    Arjay is offline Moderator / MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    12,836

    Re: Exporting Classes The Right Way, Tricks and Tips?

    If I remember correctly from earlier, you are allowing users to create plug-ins to run with your already compiled program. If this is true, you will still have the issues associated with passing c++ objects in dlls regardless of whether you define the library classes entirely in headers.

  10. #10
    2kaud's Avatar
    2kaud is online now Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    6,509

    Re: Exporting Classes The Right Way, Tricks and Tips?

    Like as been said before - c++ isn't c!

    What books/resources are you using to learn c++? See http://forums.codeguru.com/showthrea...560001-C-Books. Professional c++ is recommended.
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++17 Compiler: Microsoft VS2017 (15.9.3)

  11. #11
    Join Date
    Jul 2017
    Posts
    76

    Re: Exporting Classes The Right Way, Tricks and Tips?

    Quote Originally Posted by Arjay View Post
    If I remember correctly from earlier, you are allowing users to create plug-ins to run with your already compiled program. If this is true, you will still have the issues associated with passing c++ objects in dlls regardless of whether you define the library classes entirely in headers.
    Well one option would be to force the client to code in pure c of course this is not a good choice, I want him to be able to use the goodies of c++ oriented programming. Well, maybe somehow I can combine hpp and dlls together to achieve that. Haven't think a lot about it yet.

  12. #12
    Join Date
    Jul 2017
    Posts
    76

    Re: Exporting Classes The Right Way, Tricks and Tips?

    It just came to me, what if I let the client to implement his plugin however he like and then define an entry point function which will be the only which he's going to export on the dll and then my program is going to call that function. Is this going to work?

  13. #13
    Join Date
    Jul 2017
    Posts
    76

    Re: Exporting Classes The Right Way, Tricks and Tips?

    I tried the code below and it works! Isn't that solving my problem of the plugins (Dynamic Loading)?
    I'm not exporting any classes, just an entry point c function which i call StartPlugin()
    Basically, the Client can do whatever he wants with his code and he just need to provide only one C function
    which is going to be exported into the dll and used like an entry point of his code into my extensible application.

    Plugin DLL Code
    Code:
    #include <iostream>
    #include <string>
    
    class Base
    {	
    
    private:
    	std::string message;
    
    public:
    
    	Base(std::string msg):message(msg) 
    	{
    	}
    
    	~Base() {}
    
    
    protected:
    
    	void printMessage()
    	{
    		std::cout << message << std::endl;
    	}
    };
    
    
    
    class Plugin : public Base
    {
    
    public:
    
    	Plugin() : Base("Initializing the message...")
    	{
    	}
    
    	~Plugin()
    	{
    	}
    
    	void print()
    	{
    		printMessage();
    	}
    
    };
    
    
    extern "C" __declspec(dllexport) void StartPlugin()
    {
    	Plugin *obj = new Plugin();
    
    	obj->print();
    }

    My Awesome extensible app
    Code:
    #include <iostream>
    #include <Windows.h>
    
    
    typedef void(*StartPluginFunc)();
    
    int main()
    {
    
    	//Load The DLL.
    	HINSTANCE handle = LoadLibrary(TEXT("C:\\Users\\babaliaris\\source\\repos\\test_solution\\Debug\\Plugin.dll"));
    
    	if (!handle)
    	{
    		std::cout << "Dll specified could not be found!" << std::endl;
    		std::cin.get();
    		return -1;
    	}
    
    	//Load The StartPlugin Symbol.
    	StartPluginFunc StartPlugin = (StartPluginFunc)GetProcAddress(handle, "StartPlugin");
    
    	if (!StartPlugin)
    	{
    		std::cout << "Could not find symbol!" << std::endl;
    		std::cin.get();
    		return -1;
    	}
    
    	//Call the plugin.
    	StartPlugin();
    	std::cout << "Press ENTER to continue..." << std::endl;
    	std::cin.get();
    
    	//Unload the library.
    	FreeLibrary(handle);
    
    	return 0;
    }
    Last edited by babaliaris; December 2nd, 2018 at 06:00 PM.

  14. #14
    Arjay's Avatar
    Arjay is offline Moderator / MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    12,836

    Re: Exporting Classes The Right Way, Tricks and Tips?

    Yep, that's getting on the right track. You should supply a StopPlugin export so the caller can clean up.

  15. #15
    2kaud's Avatar
    2kaud is online now Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    6,509

    Re: Exporting Classes The Right Way, Tricks and Tips?

    Code:
    typedef void(*StartPluginFunc)();
    rather than using typedef (which is c), the c++ way would be to use using

    Code:
    using StartPlugInFunc = void(*)();
    See https://en.cppreference.com/w/cpp/language/type_alias

    Also

    Code:
    //Load The StartPlugin Symbol.
    StartPluginFunc StartPlugin = (StartPluginFunc)GetProcAddress(handle, "StartPlugin");
    in c++ would be coded as

    Code:
    const auto StartPlugin = reinterpret_cast<StartPlugInFunc>(GetProcAddress(handle, "StartPlugin"));
    See https://en.cppreference.com/w/cpp/la...interpret_cast and the links to the other c++ casts - const_cast, static_cast and dynamic_cast.
    Last edited by 2kaud; December 3rd, 2018 at 06:59 AM.
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++17 Compiler: Microsoft VS2017 (15.9.3)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  


Windows Mobile Development Center


Click Here to Expand Forum to Full Width




On-Demand Webinars (sponsored)