Found an easy way to today to use an existing C++ unmanaged class inside of C# by simply adding a reference.
Inside C++ ATL project
- Create an ATL COM DLL project (new ATL project->select DLL) and add a class (will be your wrapper class).
- Add methods that will call your C++ class methods.
- IMPORTANT: Instantiate the pointer to the class you are going to wrap in the wrapper class constructor. This follows the C# paradigm of using new to instantiate objects. If you do not do this a C# programmer may new your object and attempt to use it with disastrous results since your pointer has not been initialized. The end user of the DLL has no way of knowing you did not init the pointer and creating a separate init function is quite unwieldy and doesn't fit the mold of other C# and .NET objects.
- Add code to call the class methods via a pointer from the wrapper class.
- Compile the DLL
- Copy the DLL to the bin debug/release of your C# project
1. Right click references and add your new DLL
2. Place a using namespace <DLLName> in your C# code
3. Now you can use the class as usual with some restrictions.
Restrictions on COM objects:
- They MUST return an HRESULT
- They cannot return values in EAX or ST(0) IE: int GetValue() is not valid.
- Because of this values must either be returned on the stack or used as properties of the class.
- Data types between COM, C++, and C# are very different. You may have to adjust data types to get everything working.
- As long as the prototypes for the class functions do not change the COM object will work as expected regardless if the body of the function changes
- This DLL can now be used in C++, Managed C++, Visual Basic, and C# since it is a COM object
- This method does not require you to write a wrapper class in C# or use [DLLImport=("MyDLL.dll")]
- No changes need to be made to any C++ header or source files - IE no more __declspec(dllimport/dllexport) crapola.
- Everything is done via Wizards in ATL and the corresponding IDL files are automatically created.
Just thought I'd post this since it's very handy and I had to gather this info from about 15 different sources on the internet before I got it working.
There is another way by wrapping all of your class functions in a C-type API that calls the class functions. This is a lot of work, however, since you must create a new function for every class function you wish to export and use. This also means you probably have to alter the source files a bit. And of course you still need this:
DLL_API must be used for every function you wish to export. Not the best way to do it.Code:#ifdef DLL_EXPORTS #define DLL_API __declspec(dllexport) #else #define DLL_API __declspec(dllimport) #endif
This may qualify as a sticky since I guarantee some of you will want to do this at one time or another.