Calling a C++ lib from C#

a few months back, I found myself having to use a C++ .lib file from C#. it took a bit of looking around to figure it out, so I figured that I'd publish my cheat sheet here. I posted a number of questions about this subject to the C# interop newsgroup and found that the MVPs were excellent. if you search, you'll find these posts and be able to get better code from there - I've tried to get the examples in this post right, but the line breaks may cause confusion.

BTW - I grabbed this stuff from all over. I've tried to credit the sources, but I may have missed some. I've created a separate post about handling the unsigned char* data type from a C .lib file.

first of all, this is an awkward thing to do. if you have the choice, get a DLL instead of LIB.

1. create a C++ Win32 DLL Project from VS.Net

from: http://www.codersource.net/win32_dlls.html

Creating a Win32 dll:
- Open the New Project Wizard.
- Select Win32 Dynamic-Link Library.
- Name the project "DemoDll."
- In the next screen, select "A dll that exports some symbols" radio button.
- Click Finish.
The dll project will be created.

Now open the file DemoDll.cpp. You can see a function definition for "DEMODLL_API int fnDemoDll(void)".

Replace this function with the following code:
DEMODLL_API int fnDemoDll(int a,int b){return a+b;}

Open the DemoDll.h file and insert the declaration "DEMODLL_API int fnDemoDll(int a,int b)"

Create a new file named "DemoDll.Def" and add the following code in that file.

; DemoDll.def : Declares the module parameters for the DLL. LIBRARY "DemoDll"
DESCRIPTION 'DemoDll Windows Dynamic Link Library'
EXPORTS
; Explicit exports can go here
fnDemoDll PRIVATE

Remember to add this DemoDll.def file to the project.
Build the project. The DLL will be created.

Using the DLL
This part explains only the dynamic loading using loadlibrary. The following sample code has to be used in a new console application.

#include
#include

typedef int (*ADDITIONFUNCTION)(int a,int b);
ADDITIONFUNCTION addFunction;

void main()
{
HINSTANCE hDll;
hDll = LoadLibrary("Pathofdll");
if(hDll == NULL)
{
cout<<"Error loading win32 dll"<return ;
}
addFunction = (ADDITIONFUNCTION)GetProcAddress(hDll,"fnDemoDll");
int result;
if(addFunction != NULL)
cout<<(addFunction)(10,11)<http://www.codersource.net/win32_dlls.html

Now open a blank solution, and add a new C++ MFC Class Library Project. Let's call it MyUnmanagedDotNetVCWrapper. We will implemenet a wrapper for MyUnmanagedVC6Class:

#include "MyUnmanagedVC6Header.h"

class __declspec(dllexport) MyUnmanagedDotNetClass
{
private:
MyUnmanagedVC6Class* _class;
public:
MyUnmanagedDotNetClass(int x)
{
_class = new MyUnmanagedVC6Class(x);
}
void DoSomething(int x,double d)
{
_class->DoSomething(x,d);
}
}

This should be located in MyUnmanagedDotNetHeader.h.

Note: If you have all the sources for the original DLL you can open it in VisualStudio .NET, and it will convert it for you into a DLL you can use for the later step. This can save you the time for the first wrapper.

4. add methods to your new DLL that wrap the method in the original lib that you're trying to access from C#. newsgroup post about this topic.

Random Notes:

EXPORTS
; Explicit exports can go here
MyMMCPropertyChangeNotify @1
MyMMCFreeNotifyHandle @2
MyMMCPropPageCallback @3

after this I added the following line to mymmc.h #pragma comment(lib, "mmc.lib")

I changed one project setting and it compiled. In the General setting: Use MFC in a shared DLL.

reference this page if you have questions about marshalling data types:
http://msdn.microsoft.com/msdnmag/issues/02/08/CQA/

Example of syntax for calling the functions

// Cawood: import an ARTag sample function
[DllImport("ARTagWin32DLL.dll", EntryPoint="artag_create_marker_wrapped")]
//public static extern int artag_create_marker_wrapped(int artag_id, int scale, unsigned char *image);
public static extern int artag_create_marker_wrapped(int artag_id, int scale, [MarshalAs(UnmanagedType.LPStr)] StringBuilder image)