Click here to Skip to main content
15,892,674 members
Articles / Programming Languages / C#

NativeWrapper: A Tool for Native Interoperability

Rate me:
Please Sign up or sign in to vote.
2.84/5 (16 votes)
14 Aug 2005CPOL4 min read 97.1K   1.4K   24  
A managed wrapper for native DLLs to be used in .NET applications
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Threading;
using System.Diagnostics;
using System.IO;

namespace NativeWrapper
{
	/// <summary>
	/// Summary description for Form1.
	/// </summary>
	public class Form1 : System.Windows.Forms.Form
	{
		private System.Windows.Forms.TextBox libFile;
		private System.Windows.Forms.Label label1;
		private System.Windows.Forms.Label label2;
		private System.Windows.Forms.TextBox dllFile;
		private System.Windows.Forms.Button button1;
		private System.Windows.Forms.Button button2;
		private System.Windows.Forms.Button button3;
		private System.Windows.Forms.OpenFileDialog libFileDialog;
		private System.Windows.Forms.OpenFileDialog dllFileDialog;
		private string libFileName;
		private string dllFileName;
		private System.Collections.ArrayList functionArray = new ArrayList(10);
		/// <summary>
		/// Required designer variable.
		/// </summary>
		private System.ComponentModel.Container components = null;

		public Form1()
		{
			//
			// Required for Windows Form Designer support
			//
			InitializeComponent();

			//
			// TODO: Add any constructor code after InitializeComponent call
			//
		}

		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if (components != null) 
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}

		#region Windows Form Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
			this.libFile = new System.Windows.Forms.TextBox();
			this.label1 = new System.Windows.Forms.Label();
			this.label2 = new System.Windows.Forms.Label();
			this.dllFile = new System.Windows.Forms.TextBox();
			this.button1 = new System.Windows.Forms.Button();
			this.button2 = new System.Windows.Forms.Button();
			this.button3 = new System.Windows.Forms.Button();
			this.libFileDialog = new System.Windows.Forms.OpenFileDialog();
			this.dllFileDialog = new System.Windows.Forms.OpenFileDialog();
			this.SuspendLayout();
			// 
			// libFile
			// 
			this.libFile.Location = new System.Drawing.Point(96, 32);
			this.libFile.Name = "libFile";
			this.libFile.Size = new System.Drawing.Size(440, 20);
			this.libFile.TabIndex = 0;
			this.libFile.Text = "";
			// 
			// label1
			// 
			this.label1.Location = new System.Drawing.Point(8, 32);
			this.label1.Name = "label1";
			this.label1.Size = new System.Drawing.Size(88, 24);
			this.label1.TabIndex = 1;
			this.label1.Text = "Lib file";
			// 
			// label2
			// 
			this.label2.Location = new System.Drawing.Point(8, 64);
			this.label2.Name = "label2";
			this.label2.Size = new System.Drawing.Size(88, 24);
			this.label2.TabIndex = 3;
			this.label2.Text = "Dll file";
			// 
			// dllFile
			// 
			this.dllFile.Location = new System.Drawing.Point(96, 64);
			this.dllFile.Name = "dllFile";
			this.dllFile.Size = new System.Drawing.Size(440, 20);
			this.dllFile.TabIndex = 2;
			this.dllFile.Text = "";
			// 
			// button1
			// 
			this.button1.Location = new System.Drawing.Point(256, 120);
			this.button1.Name = "button1";
			this.button1.Size = new System.Drawing.Size(160, 56);
			this.button1.TabIndex = 4;
			this.button1.Text = "Generate Wraper";
			this.button1.Click += new System.EventHandler(this.button1_Click);
			// 
			// button2
			// 
			this.button2.Location = new System.Drawing.Point(560, 32);
			this.button2.Name = "button2";
			this.button2.Size = new System.Drawing.Size(88, 24);
			this.button2.TabIndex = 5;
			this.button2.Text = "Choose File";
			this.button2.Click += new System.EventHandler(this.button2_Click);
			// 
			// button3
			// 
			this.button3.Location = new System.Drawing.Point(560, 64);
			this.button3.Name = "button3";
			this.button3.Size = new System.Drawing.Size(88, 24);
			this.button3.TabIndex = 6;
			this.button3.Text = "Choose File";
			this.button3.Click += new System.EventHandler(this.button3_Click);
			// 
			// Form1
			// 
			this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
			this.ClientSize = new System.Drawing.Size(664, 206);
			this.Controls.Add(this.button3);
			this.Controls.Add(this.button2);
			this.Controls.Add(this.button1);
			this.Controls.Add(this.label2);
			this.Controls.Add(this.dllFile);
			this.Controls.Add(this.label1);
			this.Controls.Add(this.libFile);
			this.Name = "Form1";
			this.Text = "Native Wrapper";
			this.ResumeLayout(false);

		}
		#endregion

		/// <summary>
		/// The main entry point for the application.
		/// </summary>
		[STAThread]
		static void Main() 
		{
			Application.Run(new Form1());
		}


		// select the library file
		private void button2_Click(object sender, System.EventArgs e)
		{
			libFileDialog.DefaultExt = "lib";
			libFileDialog.ShowDialog(this);
			if (libFileDialog.FileName.CompareTo("")!=0)
			{
				this.libFileName= libFileDialog.FileName;
				this.libFile.Text= libFileDialog.FileName;
			}

		}

		// select the dll file 
		private void button3_Click(object sender, System.EventArgs e)
		{
			dllFileDialog.DefaultExt = "lib";
			dllFileDialog.ShowDialog(this);
			if (dllFileDialog.FileName.CompareTo("")!=0)
			{
				this.dllFileName= dllFileDialog.FileName;
				this.dllFile.Text= dllFileDialog.FileName;
			}

		}

		// generate the wrapper
		private void button1_Click(object sender, System.EventArgs e)
		{

			// start the dumpbin process
			Process process = new Process();
			
			try
			{
				// call the file
				process.StartInfo.UseShellExecute = false;
				process.StartInfo.RedirectStandardOutput = true;
				process.StartInfo.RedirectStandardError = false;
				process.StartInfo.CreateNoWindow = true;
				process.StartInfo.FileName = "cmd.exe";
				process.StartInfo.Arguments = "/k \"vsvars32 && dumpbin "+ "\""+ this.libFileName+"\""+" /exports "+ " >"+"\""+this.libFileDialog.FileName+".funcs"+"\"" +"\"";
				process.StartInfo.WorkingDirectory= Application.StartupPath;
				process.Start();
			
			}
			catch (Exception exc)
			{
				MessageBox.Show(this,exc.Message);
			}
			

			//wait for the process to produce the funcs file
			Thread.Sleep(2000);
			try
			{
			
				//read the file
				StreamReader sr = new StreamReader(this.libFileDialog.FileName+".funcs");
				String line="";
				while ((line=sr.ReadLine())!=null)
				{
					if (line.IndexOf("ordinal")>0 && line.IndexOf("name")>0)
					{
						break;
					}
				}
				// jump a line
				line=sr.ReadLine();

				//starting reading the functions
				while ((line=sr.ReadLine())!=null)
				{
					if (line.IndexOf("Summary")>0)
					{
						break;
					}
					functionArray.Add(new Function(line.Trim(),this.dllFileName));
				}

				// process the functions
				foreach (Object o in this.functionArray)
				{
					try
					{
						(o as Function).processFunction();
					}
					catch
					{
					}
				}
			}
			catch (Exception exc)
			{
				MessageBox.Show(this,exc.Message);
			}


			// generate the code for the wrapper
			string path = Path.GetDirectoryName(this.libFileName)+"\\"+(this.functionArray[0] as Function).NameSpaceName;
			DirectoryInfo di=null;

			try 
			{
				// Try to create the directory.
				 di = Directory.CreateDirectory(path);
			} 
			catch (Exception exc) 
			{
				MessageBox.Show(this,exc.Message);
			} 

			try
			{
				String wrapperCode="";
				wrapperCode+="// "+ (this.functionArray[0] as Function).NameSpaceName + "\n";
				wrapperCode+="#pragma once" + "\n";
				wrapperCode+="#using <mscorlib.dll>" + "\n";
				wrapperCode+="using namespace System;"+ "\n";
				wrapperCode+="using namespace System::Runtime::InteropServices; "+ "\n";
				wrapperCode+="namespace "+  (this.functionArray[0] as Function).NameSpaceName + "\n";
				wrapperCode+="{\n";

				foreach (Object o in this.functionArray)
				{
					if ((o as Function ).Name != null)
					{
						wrapperCode+= "\t// generated from "+(o as Function ).Definition+"\n";
						wrapperCode+= (o as Function ).StaticDeclaration;
						wrapperCode+= "\n";
					}
				}

				wrapperCode+="\t//#pragma comment(lib, \""+(this.functionArray[0] as Function).NameSpaceName+".lib\")";
				wrapperCode+= "\n";
				wrapperCode+= "\tpublic __gc class "+(this.functionArray[0] as Function).NameSpaceName;
				wrapperCode+= "\n\t{\n";
				wrapperCode+= "	public:";
			
				foreach (Object o in this.functionArray)
				{
					if ((o as Function ).Name != null)
					{
						wrapperCode+= "\n\t// wrapper for "+(o as Function ).Definition+"\n";
						wrapperCode+= (o as Function ).inClassDefinition;
						wrapperCode+= "\n\n";
					}
				}
				wrapperCode+="\t};\n}\n";

				StreamWriter sw = new StreamWriter(di.FullName+"\\"+(this.functionArray[0] as Function).NameSpaceName+".h");
				sw.Write(wrapperCode);
				sw.Close();
			}
			catch (Exception exc)
			{
				MessageBox.Show(this,exc.Message);
			}

			// generate the code for the project
			try
			{
				String projectCode="";
				projectCode+="<?xml version=\"1.0\" encoding=\"Windows-1252\"?>\n <VisualStudioProject ProjectType=\"Visual C++\" 	 Version=\"7.10\"  Name=\" ";
				projectCode+= (this.functionArray[0] as Function).NameSpaceName + "\"";
				projectCode+= " ProjectGUID=\"{C1E15014-A680-4404-A66C-002A994C9C2E}\" \n RootNamespace=\" ";
				projectCode+= (this.functionArray[0] as Function).NameSpaceName + "\"";
				projectCode+= "	Keyword=\"ManagedCProj\"> \n";
				projectCode+= "		 <Platforms> \n";
				projectCode+= "		 <Platform \n";
				projectCode+= "		  Name=\"Win32\"/> \n";
				projectCode+= "		  </Platforms> \n";
				projectCode+= "		<Configurations> \n";
				projectCode+= "		 <Configuration \n";
				projectCode+= "			  Name=\"Debug|Win32\" \n";
				projectCode+= "	  OutputDirectory=\"$(SolutionDir)$(ConfigurationName)\" \n";
				projectCode+= "		  IntermediateDirectory=\"$(ConfigurationName)\" \n";
				projectCode+= "		  ConfigurationType=\"2\" \n";
				projectCode+= "			  CharacterSet=\"2\" \n";
				projectCode+= "	 ManagedExtensions=\"TRUE\"> \n";
				projectCode+= "		  <Tool \n";
				projectCode+= "		   Name=\"VCCLCompilerTool\" \n";
				projectCode+= "			   AdditionalOptions=\"/Zl\" \n";
				projectCode+= "	   Optimization=\"0\" \n";
				projectCode+= "	  PreprocessorDefinitions=\"WIN32;_DEBUG\" \n";
				projectCode+= "	  MinimalRebuild=\"FALSE\" \n";
				projectCode+= "	   BasicRuntimeChecks=\"0\" \n";
				projectCode+= "	   RuntimeLibrary=\"1\" \n";
				projectCode+= "	   UsePrecompiledHeader=\"3\" \n";
				projectCode+= "	   WarningLevel=\"3\" \n";
				projectCode+= "		   DebugInformationFormat=\"3\"/> \n";
				projectCode+= "		   <Tool \n";
				projectCode+= "			   Name=\"VCCustomBuildTool\"/> \n";
				projectCode+= "			   <Tool \n";
				projectCode+= "		   Name=\"VCLinkerTool\" \n";
				projectCode+= "		   AdditionalOptions=\"/noentry\" \n";
				projectCode+= "		   AdditionalDependencies=\"nochkclr.obj mscoree.lib\" \n";
				projectCode+= "					   OutputFile=\"$(OutDir)\\$(ProjectName).dll\" \n";
				projectCode+= "					   LinkIncremental=\"2\" \n";
				projectCode+= "			   GenerateDebugInformation=\"TRUE\" \n";
				projectCode+= "					   AssemblyDebug=\"1\"/> \n";
				projectCode+= "					   <Tool \n";
				projectCode+= "				   Name=\"VCMIDLTool\"/> \n";
				projectCode+= "				   <Tool \n";
				projectCode+= "					   Name=\"VCPostBuildEventTool\"/> \n";
				projectCode+= "					   <Tool \n";
				projectCode+= "			   Name=\"VCPreBuildEventTool\"/> \n";
				projectCode+= "	   <Tool \n";
				projectCode+= "				   Name=\"VCPreLinkEventTool\"/> \n";
				projectCode+= "					   <Tool \n";
				projectCode+= "					   Name=\"VCResourceCompilerTool\"/> \n";
				projectCode+= "			   <Tool \n";
				projectCode+= "			   Name=\"VCWebServiceProxyGeneratorTool\"/> \n";
				projectCode+= "	   <Tool \n";
				projectCode+= "			   Name=\"VCXMLDataGeneratorTool\"/> \n";
				projectCode+= "		   <Tool \n";
				projectCode+= "		   Name=\"VCWebDeploymentTool\"/> \n";
				projectCode+= "	   <Tool \n";
				projectCode+= "					   Name=\"VCManagedWrapperGeneratorTool\"/> \n";
				projectCode+= "				   <Tool \n";
				projectCode+= "				   Name=\"VCAuxiliaryManagedWrapperGeneratorTool\"/> \n";
				projectCode+= "				   </Configuration> \n";
				projectCode+= "			 <Configuration \n";
				projectCode+= "						  Name=\"Release|Win32\" \n";
				projectCode+= "				  OutputDirectory=\"$(SolutionDir)$(ConfigurationName)\" \n";
				projectCode+= "					  IntermediateDirectory=\"$(ConfigurationName)\" \n";
				projectCode+= "					  ConfigurationType=\"2\" \n";
				projectCode+= "			  CharacterSet=\"2\" \n";
				projectCode+= "			  ManagedExtensions=\"TRUE\"> \n";
				projectCode+= "		  <Tool \n";
				projectCode+= "					   Name=\"VCCLCompilerTool\" \n";
				projectCode+= "		   AdditionalOptions=\"/Zl\" \n";
				projectCode+= "				   PreprocessorDefinitions=\"WIN32;NDEBUG\" \n";
				projectCode+= "			   MinimalRebuild=\"FALSE\" \n";
				projectCode+= "					   RuntimeLibrary=\"0\" \n";
				projectCode+= "					   UsePrecompiledHeader=\"3\" \n";
				projectCode+= "				   WarningLevel=\"3\" \n";
				projectCode+= "		   DebugInformationFormat=\"3\"/> \n";
				projectCode+= "					   <Tool \n";
				projectCode+= "			   Name=\"VCCustomBuildTool\"/> \n";
				projectCode+= "		   <Tool \n";
				projectCode+= "		   Name=\"VCLinkerTool\" \n";
				projectCode+= "			   AdditionalOptions=\"/noentry\" \n";
				projectCode+= "			   AdditionalDependencies=\"nochkclr.obj mscoree.lib\" \n";
				projectCode+= "				   OutputFile=\"$(OutDir)\\$(ProjectName).dll\" \n";
				projectCode+= "	   LinkIncremental=\"1\" \n";
				projectCode+= "					   GenerateDebugInformation=\"TRUE\"/> \n";
				projectCode+= "					   <Tool \n";
				projectCode+= "			   Name=\"VCMIDLTool\"/> \n";
				projectCode+= "					   <Tool \n";
				projectCode+= "			   Name=\"VCPostBuildEventTool\"/> \n";
				projectCode+= "				   <Tool \n";
				projectCode+= "				   Name=\"VCPreBuildEventTool\"/> \n";
				projectCode+= "						   <Tool \n";
				projectCode+= "		   Name=\"VCPreLinkEventTool\"/> \n";
				projectCode+= "	<Tool \n";
				projectCode+= "	Name=\"VCResourceCompilerTool\"/> \n";
				projectCode+= "	<Tool \n";
				projectCode+= "	Name=\"VCWebServiceProxyGeneratorTool\"/> \n";
				projectCode+= "	<Tool \n";
				projectCode+= "	Name=\"VCXMLDataGeneratorTool\"/> \n";
				projectCode+= "	<Tool \n";
				projectCode+= "	Name=\"VCWebDeploymentTool\"/> \n";
				projectCode+= "	<Tool \n";
				projectCode+= "	Name=\"VCManagedWrapperGeneratorTool\"/> \n";
				projectCode+= "	<Tool \n";
				projectCode+= "	Name=\"VCAuxiliaryManagedWrapperGeneratorTool\"/> \n";
				projectCode+= "	</Configuration> \n";
				projectCode+= "	</Configurations> \n";
				projectCode+= "	<References> \n";
				projectCode+= "	<AssemblyReference \n";
				projectCode+= "	RelativePath=\"mscorlib.dll\"/> \n";
				projectCode+= "	<AssemblyReference \n";
				projectCode+= "	RelativePath=\"System.dll\"/> \n";
				projectCode+= "	<AssemblyReference \n";
				projectCode+= "	RelativePath=\"System.Data.dll\"/> \n";
				projectCode+= "	</References> \n";
				projectCode+= "	<Files> \n";
				projectCode+= "	<Filter \n";
				projectCode+= "	Name=\"Source Files\" \n";
				projectCode+= "	Filter=\"cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx\" \n";
				projectCode+= "	UniqueIdentifier=\"{4FC737F1-C7A5-4376-A066-2A32D752A2FF}\"> \n";
				projectCode+= "	<File \n";
				projectCode+= "	RelativePath=\".\\AssemblyInfo.cpp\"> \n";
				projectCode+= "	</File> \n";
				projectCode+= "	<File \n";
				projectCode+= " 	RelativePath=\".\\";
				projectCode+= (this.functionArray[0] as Function).NameSpaceName + ".cpp\">";
				projectCode+= " 	</File> \n";
				projectCode+= " 		<File \n";
				projectCode+= " 			 RelativePath=\".\\Stdafx.cpp\"> \n";
				projectCode+= " 			 <FileConfiguration \n";
				projectCode+= " 				  Name=\"Debug|Win32\"> \n";
				projectCode+= "<Tool \n";
				projectCode+= "Name=\"VCCLCompilerTool\" \n";
				projectCode+= "UsePrecompiledHeader=\"1\"/> \n";
				projectCode+= "</FileConfiguration> \n";
				projectCode+= "<FileConfiguration \n";
				projectCode+= "Name=\"Release|Win32\"> \n";
				projectCode+= "<Tool \n";
				projectCode+= "Name=\"VCCLCompilerTool\" \n";
				projectCode+= "UsePrecompiledHeader=\"1\"/> \n";
				projectCode+= "</FileConfiguration> \n";
				projectCode+= "</File> \n";
				projectCode+= "</Filter> \n";
				projectCode+= "<Filter \n";
				projectCode+= "Name=\"Header Files\" \n";
				projectCode+= "Filter=\"h;hpp;hxx;hm;inl;inc;xsd\" \n";
				projectCode+= "UniqueIdentifier=\"{93995380-89BD-4b04-88EB-625FBE52EBFB}\"> \n";
				projectCode+= "<File \n";
				projectCode+= " 	RelativePath=\".\\";
				projectCode+= (this.functionArray[0] as Function).NameSpaceName + ".h\">";
				projectCode+= "	</File> \n";
				projectCode+= "		 <File \n";
				projectCode+= "			  RelativePath=\".\\Stdafx.h\"> \n";
				projectCode+= "			  </File> \n";
				projectCode+= "			  </Filter> \n";
				projectCode+= "						 <File \n";
				projectCode+= "						  RelativePath=\".\\ReadMe.txt\"> \n";
				projectCode+= "					  </File> \n";
				projectCode+= "						  </Files> \n";
				projectCode+= "					  <Globals> \n";
				projectCode+= "					   </Globals> \n";
				projectCode+= "			   </VisualStudioProject> \n";

				StreamWriter sw = new StreamWriter(di.FullName+"\\"+(this.functionArray[0] as Function).NameSpaceName+".vcproj");
				sw.Write(projectCode);
				sw.Close();


			}
			catch (Exception exc)
			{
				MessageBox.Show(this,exc.Message);
			}

			//generate the cpp code
			try
			{
				String cppCode="";
				cppCode+="#include \"stdafx.h\"\n";
				cppCode+="#include \""+(this.functionArray[0] as Function).NameSpaceName+".h\"";
				StreamWriter sw = new StreamWriter(di.FullName+"\\"+(this.functionArray[0] as Function).NameSpaceName+".cpp");
				sw.Write(cppCode);
				sw.Close();
			}
			catch (Exception exc)
			{
				MessageBox.Show(this,exc.Message);
			}

			File.Copy(Application.StartupPath+"\\res\\AssemblyInfo.cpp", di.FullName+"\\AssemblyInfo.cpp",true);
			File.Copy(Application.StartupPath+"\\res\\Stdafx.cpp", di.FullName+"\\Stdafx.cpp",true);
			File.Copy(Application.StartupPath+"\\res\\Stdafx.h", di.FullName+"\\Stdafx.h",true);

			MessageBox.Show(this,"Wrapping completed");

		}
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
Italy Italy
2008 - Working on my own
2005 - ... still programming
2005 - Working at the Digigroup of Torino (Italy)
2004 - Got my PhD at the "Politecnico di Torino"
2001 - Got Graduated at the "Politecnico di Torino"
2000 - Got Graduated at the UIC (Chicago)
1983 - Started programming ...
1976 - Born

Comments and Discussions