It is perfectly possible and quite common. A DLL needs an entry point called DllMain() and then you need to export your functions. If you start a new C++ Win32 project, you can select DLL as type of project and you'll get the entry point and the precompiled header, and all you need to do is write your functions.
But beware: You cannot export C++ classes or complex structures in general. You can only use POD structs and you must export your functions using extern "C". This is easier than it sounds.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
//Put this in stdafx.h
#ifdef COMPILEDLL
#define DLL __declspec(export)
#else
#define DLL __declspec(import)
#endif
//Put this in the main function header file.
#pragma once
//A POD struct sample
typedef struct _SampleData
{
int a;
double b;
} SampleData, *LPSampleData;
extern "C"
{
DLL int MySum(int a, int b);
DLL double SomeComplexCalculation(LPSampleData data);
}
|
Then in a CPP file you write the function bodies for the functions you declare in the previous header file. When you compile, #define the symbol called COMPILEDLL. You can do this in the project settings or at the top of stdafx.h. And voilá, the resulting dll will have entry points for your functions. You can verify this with Dependency Walker (www.dependencywalker.com).
This is the first part. The second part is .Net marshaling from your C# application. The above function signatures would look like this in C#:
1 2 3 4 5 6 7 8 9 10 11 12
|
public struct SampleData
{
public int a;
public double b;
}
public static class MyDLL
{
[DllImport("mydll.dll")
public static extern int MySum(int a, int b);
[DllImport("mydll.dll")
public static extern double SomeComplexCalculation(ref SampleData data);
}
|
That is in a nutshell. If you want specifics of any part of the procedure, you should Google up a good tutorial on the matter. And note that the above is just a simple example. The signatures get more complex when they involve strings and other data types, and even more complex when the DLL allocates memory that goes beyond the DLL boundary, meaning a deallocation routine also needs to be provided.