How to Export a C++ Class from a Dll

How to export a C++ class from a dll?

A common approach is to have a single macro (let's call it EXPORT) which either expands to dllimport or dllexport depending on whether some sort of "building the DLL right now" define is set, like this:

#ifdef MAKEDLL
# define EXPORT __declspec(dllexport)
#else
# define EXPORT __declspec(dllimport)
#endif

class EXPORT xyz {
// ...
};

The idea is that when building your DLL, you add MAKEDLL to the preprocessor definitions. That way, all the code will be exported. Clients who link against your DLL (and hence include this header file) don't need to do anything at all. By not defining MAKEDLL, they will automatically import all the code.

The advantage of this approach is that the burden of getting the macros right is moved from the many (the clients) to just the author of the DLL.

The disadvantage of this is that when using the code above as it is, it's no longer possible to just compile the code directly into some client module since it's not possible to define the EXPORT macro to nothing. To achieve that, you'd need to have another check which, if true, defines EXPORT to nothing.

On a slightly different topic: in many cases, it's not possible (or desired!) to export a complete class like that. Instead, you may want to just export the symbols you need. For instance, in your case, you may want to just export the two public methods. That way, all the private/protected members won't be exported:

class xyz
{
public:
EXPORT void printing();
EXPORT void printing(int a);
};

Exporting a C++ class from a DLL

What about late-binding? As in loading
it with LoadLibrary() and
GetProcAddress() ? I'm used being able
to load the library at run time and it
would be great if you could do that
here.

So there are two ways to load the DLL. The first is to reference one or more symbols from the DLL (your classname, for example), supply an appropriate import .LIB and let the linker figure everything out.

The second is to explicitly load the DLL via LoadLibrary.

Either approach works fine for C-level function exports. You can either let the linker handle it or call GetProcAddress as you noted.

But when it comes to exported classes, typically only the first approach is used, i.e., implicitly link to the DLL. In this case the DLL is loaded at application start time, and the application fails to load if the DLL can't be found.

If you want to link to a class defined in a DLL, and you want that DLL to be loaded dynamically, sometime after program initiation, you have two options:

  1. Create objects of the class using a special factory function, which internally will have to use (a tiny bit of) assembler to "hook up" newly created objects to their appropriate offsets. This has to be done at run-time AFTER the DLL has been loaded, obviously. A good explanation of this approach can be found here.

  2. Use a delay-load DLL.

All things considered... probably better to just go with implicit linking, in which case you definitely want to use the preprocessor technique shown above. In fact, if you create a new DLL in Visual Studio and choose the "export symbols" option these macros will be created for you.

Good luck...

How to export a C++ class library to C# using a dll?

You cannot import native C++ classes directly to C#. They need to be wrapped one way or another. You can wrap them with C style non-member functions. You'll need to export functions that create and destroy the instances. All in all it's pretty horrid process.

The smart way to do this is to wrap compile the native C++ code into a mixed-mode C++/CLI assembly. You can then expose the functionality as a managed ref class. The interop then becomes trivial and you don't need to run the gauntlet of writing p/invoke declarations by hand.

How do I DllExport a C++ Class for use in a C# Application

C# cannot directly import C++ classes (which are effectively name-mangled C interfaces).

Your options are exposing the class via COM, creating a managed wrapper using C++/CLI or exposing a C-style interface. I would recommend the managed wrapper, since this is easiest and will give the best type safety.

A C-style interface would look something like this (warning: untested code):

extern "C" __declspec(dllexport)
void* CExampleExport_New(int param1, double param2)
{
return new CExampleExport(param1, param2);
}

extern "C" __declspec(dllexport)
int CExampleExport_ReadValue(void* this, int param)
{
return ((CExampleExport*)this)->ReadValue(param)
}

A C++/CLI-style wrapper would look like this (warning: untested code):

ref class ExampleExport
{
private:
CExampleExport* impl;
public:
ExampleExport(int param1, double param2)
{
impl = new CExampleExport(param1, param2);
}

int ReadValue(int param)
{
return impl->ReadValue(param);
}

~ExampleExport()
{
delete impl;
}
};

Exporting classes from a DLL

Would exporting BookStore will also export BookCollection and Book indirectly or they also need the macro for export?

They also need the macro.

The compiler only exports what is marked for export. It doesn't automatically export arguments nor return types for methods and functions that are being exported.

As follows;

class BOOKSTORE_API Book
{
std::string title;
std::string publisher;
char * getTitle();
char * getPublisher();
}

class BOOKSTORE_API BookCollection
{
std::vector<Book> books;
int getBooksCount();
Book getBook(int location);
}

class BOOKSTORE_API BookStore {
// ...
};

You will get additional warnings about the members not being exported. Provided you use the same compiler and settings for the dll and the exe, these are largely noise and can be silenced (or disabled).

A more comprehensive alternative is the pimpl pattern and remove the std::vector et. al. from the class definition(s) and the standard library members would not need to be exported from the dll. MSDN has a nice article on this.

class BOOKSTORE_API BookCollection {
protected:
struct Pimpl;
Pimpl* pimpl_;
}

// in the cpp compiled into the dll
struct BookCollection::Pimpl {
// ...
std::vector<Book> books;
// ...
}

On the "rule of three" and the "rule of five" and the unresolved symbol(s)...

When exporting classes from a dll, it is best to export all the special members as well to avoid unresolved symbol errors. This is especially applicable if using the pimpl idiom.


[S]uppose all these classes are in different files, should the macro remain the same or [does it] need to be changed per file?

Keep the macro and the #define that contains it the same per dll. So, if for the single dll, they are in three files, then they all use the same #define block. Essentially you are controlling the import/export on a per dll basis. I would also put the define block into a header of its own and include it in the header for each class (but that is not needed).

[F]rom this simple example, would [a] different msvc compiler version or CRT of the client code raise undefined behaviour as I am aware that returning [an] STL object would cause this. Since in this code, the getter only return primitive C datatype, would it be a problem as well?

Yes, different compiler versions and standard libraries could/would cause problems. E.g. even if all the constructors, assignment operators and destructors were exported from the dll, the client still needs to allocate the correct amount of space (via. new or on the stack) for objects of this class. Different standard libraries could have different sizes for std::string etc. and mixing them will create memory corruption etc. In this respect, the pimpl or NVI (non-virtual interface or template patten) is better.

How to export C++ class as a dll?

From MSDN

To export all of the public data members and member functions in a class, the keyword must appear to the left of the class name as follows:

class __declspec(dllexport) CExampleExport : public CObject
{ ... class definition ... };

Also, consider that there are more ways to do this, like .DEF-files.
Take your time to read through the explanations on the MSDN-site.

C++ | DLL / EXE - How to call another class method from exported class?

You need to add __declspec(dllexport) to every class and function you want to be available outside of your dll, you don't need to mark methods as long as the containing class is exported.

Note in classes the declspec goes between class and the class name:

class __declspec(dllexport) Exported
{
};

You'll also need a macro defined which switches your headers between __declspec(dllexport) and __declspec(dllimport) depending on whether you are building your dll or exe, e.g.:

#ifdef BUILDING_MYDLL
#define MYDLL_EXPORT __declspec(dllexport)
#else
#define MYDLL_EXPORT __declspec(dllimport)
#endif

class MYDLL_EXPORT Exported
{
};

Is is possible to export functions from a C# DLL like in VS C++?

Unmanaged Exports =>
https://sites.google.com/site/robertgiesecke/Home/uploads/unmanagedexports

DLLExport => https://github.com/3F/DllExport

How does it work?


Create a new classlibrary or proceed with an existing one.
Then add the UnmanagedExports Nuget package.

This is pretty much all setup that is required.

Now you can write any kind of static method, decorate it with [DllExport] and use it from native code.

It works just like DllImport, so you can customize the marshalling of parameters/result with MarshalAsAttribute.

During compilation, my task will modify the IL to add the required exports...

Importing a class from a c# dll into a c++ app

I normally do this kind of stuff by creating a static C++ CLR Wrapper Lib.

These are the steps I'm normally using (although I don't use it very often):

Here minimal example with using Visual Studio:

1. Create managed C# .NET library Project

Let name it HelloLibManaged
with one file Hello.cs and following content:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace HelloLibManaged
{
public class Hello
{
public void Print()
{
System.Console.WriteLine("Hello from Managed Lib");
}
}
}

Build this lib with x86 or x64 , just dont Any CPU

2. Create a new C++ CLR static lib project within same solution.
Let's name it HelloLibCpp

  • Add a reference to HelloLibManaged project via Project->Add Reference

  • Remove automatic created existing .h/.cpp files from Project, and create these 2 files:

HelloUnmanaged.h

#pragma once

namespace hello_managed {

class Hello
{
public:
void Print();
};
}

and

HelloUnmanaged.cpp:

#include "HelloUnmanaged.h"

namespace hello_managed
{

void Hello::Print()
{
HelloLibManaged::Hello^ hello = gcnew HelloLibManaged::Hello();
hello->Print();
}

}

Und Project Properties -> General specify static lib.
In the Build settings specify x86 / x64 - use the same build type as building Managed lib from Step 1.

Now you can build the dll and use it in your other unmanaged C++ projects.

For more advanced stuff, like return types and methods with parameters you have to do Type-Marshalling between managed/unmanaged code. There are many resources online with more information about Type-Conversion between managed/unmanaged code. Keyword: Marshaling.



Related Topics



Leave a reply



Submit