calling unmanaged code from c-sharp
There may be lot of situations in which we may need to call unmanaged code from our managed code. Below are the some of the situations:
1. If customer doesn't want to convert his old(Vc++ apps) applications to new .net technologies but still he wants to make new applications in.net code, in that case his new applications will have to interact with unmanaged code.
2. some of the customers are still having sentiments in writing their calculation engine code in unmanaged code mainly C++ code due to performance reasons.
Below the are steps to consume VC++ dll in C#.NET code.
Step 1 :Create unmanaged Assembly(dll)
- Create a project using VC++ Win 32 Project template.
once we provide the project name, it will open up the wizard which will look like below,please select DLL from Application type for creating DLL and also select Export Symbols if you would like to debug unmanaged code.
once you finish with the wizard the project structure will look similar to the one below:
below is a code for the TestProject.cpp file, which will have 2 functions(one returning flot and one returning string) which can be consumed by any external application.
// TestProject.cpp : Defines the exported functions for the DLL application.
//
#include "stdafx.h"
#include "TestProject.h"
// This is an example of an exported variable
TESTPROJECT_API int nTestProject=0;
// This is an example of an exported function.
TESTPROJECT_API int fnTestProject(void)
{
return 42;
}
// This is the constructor of a class that has been exported.
// see TestProject.h for the class definition
CTestProject::CTestProject()
{
return;
}
// User Defined Functions starts Here
extern "C" TESTPROJECT_API float fnMyWin32Function(float a,float b)
{
return a*b;
}
extern "C" TESTPROJECT_API char* fnMyWin32Functionstr()
{
return "Test string";
}
-----------------------------------------------------------------------------------------------------------------
Build the project, it will create the dll for you. till this point you are done with creating unmanaged assembly.
Step 2: Consuming and Debugging Unmanaged Assembly in .NET Code.
Create any type of C#.NET Project(for this Article we have chosen Console Application).
Initially we have to defined the vc++ functions that we would be calling from C#.net code and also we have to decorate it with DllImport Attribute. the signature of the function will be .net specific but data type that we are mentioning here in C#.net code must be compatible with the one in vc++ code.
--------------------------------------------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
namespace ConsoleApplication5
{
class Program
{
[DllImport("TestProject.dll")]
private static extern Single fnMyWin32Function(Single a, Single b);
[DllImport("TestProject.dll")]
private static extern string fnMyWin32Functionstr();
static void Main(string[] args)
{
Single a = 10.0f;
Single b = 20.0f;
Single c = fnMyWin32Function(a, b);
string s = fnMyWin32Functionstr();
System.Console.WriteLine(c);
System.Console.WriteLine(s);
System.Console.ReadLine();
}
}
}
--------------------------------------------------------------------------------------------------------------
Build this code, one point to remember here is if your unmanaged dll are not shared then copy the vc++ code dll that we created previously along with the debug symbols file to the working directory of the application (which in this case is bin\debug) folder of C#.NET application.
once you run the .net application, you will get result like the below:
So all done to call unmanaged functions from Managed code.
Visual Studio 2010 provides us the flexibility to debug unmanaged code from C#.NET application, below is a setting which you need to enable for unamnaged code debugging:
once you check the "Enable unmanaged code debugging" property, you can easily debug your unmanaged code by using F10 and F11 keys.
Happy Coding :-)
Comments
Anonymous
August 21, 2011
Nice Post...Always thought about DllImport as a means for calling WinAPI. Never occurred to me about writing new code in C++ and calling it in .Net.Anonymous
August 22, 2011
Thanks Sohail...Anonymous
November 29, 2015
I like the approach and can byuild successfully. However, only fnMyWin32Function actually works. fnMyWin32Functionstr crashes: // Managed Debugging Assistant 'PInvokeStackImbalance' has detected a problem in //'...TestForm.exe'. // Additional information : A call to PInvoke function 'TestForm!TestHook.MainForm::fnMyWin32Function' // has unbalanced the stack. // This is likely because the managed PInvoke signature does not match the unmanaged target signature. // Check that the calling convention and parameters of the PInvoke signature match the target unmanaged signature. I have modified the [DllImport] attribute: [DllImport("TestProject.dll", CharSet = CharSet.Auto, CallingConvention= CallingConvention.Cdecl, SetLastError = true)] [return: MarshalAs(UnmanagedType.LPStr)] private static extern string fnMyWin32Functionstr();Anonymous
November 30, 2015
A more useful example would be one that showed how to access a class method from CTestProject