Call Unmanaged Code. Part 1 - Simple DLLImport
来源:互联网 发布:mac删除系统自带软件 编辑:程序博客网 时间:2024/06/04 19:12
Call Unmanaged Code. Part 1 - Simple DLLImportBy Vyacheslav Biktagirov
Managed world is beautiful, I have all classes I want in FrameWork.. But what if I want call some unmanaged code? For instance, I have DLL written in C++, and want use it from C#.
Let's look some code. Our DLL exports some function, in CDecl convention, that sums two integers:
extern "C" __declspec(dllexport) __cdecl int sum(int a,int b);
And, of course, we want reuse this code in C#. We must recall, that it is no "direct" way to call unmanaged code, but we must inform the compiler, what we want to call, how, and where is needed code located.
[DllImport("TestDll.dll", EntryPoint="sum",ExactSpelling=false,CallingConvention=CallingConvention.Cdecl)]static extern int sum(int a,int b);and now we can call it like normal C# function.
x=5;y=7;z=sum(x,y);// x will receive 12Here is full C# client code - tested for Beta2.
using System;using System.Drawing;using System.Collections;using System.ComponentModel;using System.Windows.Forms;using System.Data;using System.Runtime.InteropServices;namespace WindowsApplication6{///It sounds very simple, becouse "int" is isomorphic type, says, int in C# and ind C++ is identical. What we can do, when we want operate non-isomorhic types, like String? Recall, that .NET string is some Class, while C++ string is char*,or wchar_t*,or BSTR, .. String may be embedded in a structure, or pointed by pointer, or even something more exotic. Let's call some string function./// Summary description for Form1./// public class Form1 : System.Windows.Forms.Form{private System.Windows.Forms.Button button1;private System.Windows.Forms.TextBox textBox1;private System.Windows.Forms.Label label1;private System.Windows.Forms.TextBox textBox2;private System.Windows.Forms.Label label2;private System.Windows.Forms.TextBox textBox3;/// /// Required designer variable./// private System.ComponentModel.Container components = null;public Form1(){//// Required for Windows Form Designer support//InitializeComponent();//// TODO: Add any constructor code after InitializeComponent call//}/// /// Clean up any resources being used./// protected override void Dispose( bool disposing ){if( disposing ){if (components != null){components.Dispose();}}base.Dispose( disposing );}#region Windows Form Designer generated code/// /// Required method for Designer support - do not modify/// the contents of this method with the code editor./// private void InitializeComponent(){this.button1 = new System.Windows.Forms.Button();this.textBox1 = new System.Windows.Forms.TextBox();this.label1 = new System.Windows.Forms.Label();this.textBox2 = new System.Windows.Forms.TextBox();this.label2 = new System.Windows.Forms.Label();this.textBox3 = new System.Windows.Forms.TextBox();this.SuspendLayout();//// button1//this.button1.Location = new System.Drawing.Point(64, 192);this.button1.Name = "button1";this.button1.Size = new System.Drawing.Size(144, 64);this.button1.TabIndex = 0;this.button1.Text = "call sum";this.button1.Click += new System.EventHandler(this.button1_Click);//// textBox1//this.textBox1.Location = new System.Drawing.Point(40, 120);this.textBox1.Name = "textBox1";this.textBox1.Size = new System.Drawing.Size(72, 22);this.textBox1.TabIndex = 1;this.textBox1.Text = "2";//// label1//this.label1.Location = new System.Drawing.Point(128, 128);this.label1.Name = "label1";this.label1.Size = new System.Drawing.Size(16, 16);this.label1.TabIndex = 2;this.label1.Text = "+";//// textBox2//this.textBox2.Location = new System.Drawing.Point(152, 120);this.textBox2.Name = "textBox2";this.textBox2.Size = new System.Drawing.Size(56, 22);this.textBox2.TabIndex = 3;this.textBox2.Text = "3";//// label2//this.label2.Location = new System.Drawing.Point(224, 120);this.label2.Name = "label2";this.label2.Size = new System.Drawing.Size(24, 23);this.label2.TabIndex = 4;this.label2.Text = "=";//// textBox3//this.textBox3.Location = new System.Drawing.Point(248, 120);this.textBox3.Name = "textBox3";this.textBox3.Size = new System.Drawing.Size(112, 22);this.textBox3.TabIndex = 5;this.textBox3.Text = "5";//// Form1//this.AutoScaleBaseSize = new System.Drawing.Size(6, 15);this.ClientSize = new System.Drawing.Size(576, 322);this.Controls.AddRange(new System.Windows.Forms.Control[] {this.textBox3,this.label2,this.textBox2,this.label1,this.textBox1,this.button1});this.Name = "Form1";this.Text = "Form1";this.ResumeLayout(false);}#endregion/// /// The main entry point for the application./// [STAThread]static void Main(){Application.Run(new Form1());}#region My Code#region Dll Imports[DllImport("TestDll.dll", EntryPoint="sum",ExactSpelling=false,CallingConvention=CallingConvention.Cdecl)]static extern int sum(int a,int b);#endregion#region Button Click Eventsprivate void button1_Click(object sender, System.EventArgs e){textBox3.Text=(int.Parse(textBox1.Text)+int.Parse(textBox2.Text)).ToString();}#endregion#endregion}}
[DllImport("Advapi32.dll", EntryPoint="GetUserName", ExactSpelling=false, SetLastError=true)]static extern bool GetUserName([MarshalAs(UnmanagedType.LPArray)] byte[] lpBuffer,[MarshalAs(UnmanagedType.LPArray)] Int32[] nSize );This function receives two parameters: char* and int*. Becouse we must allocate char* buffer and receive string by pointer, we can't use UnmanagedType.LPStr attribute, so we pass ANSI string as byte array. int* is more simple-it's 1-element Int32 array. Let's call it:
private void button2_Click(object sender, System.EventArgs e){byte[] str=new byte[20];Int32[] len=new Int32[1];len[0]=20;GetUserName(str,len);MessageBox.Show(System.Text.Encoding.ASCII.GetString(str));}We allocate 20 bytes for receiving ANSI string,one element in Int32 array, set 20 as max string length and call it. For receiving string from byte array I used Text.Encoding.ASCII class.
That's enough for first part. Second part will speak about more complex interop.
- Call Unmanaged Code. Part 1 - Simple DLLImport
- Call Unmanaged Code Part 2 - Marshal Class
- Passing Managed Structures With Arrays To Unmanaged Code Part 1
- Passing Managed Structures With Arrays To Unmanaged Code Part 2
- Passing Managed Structures With Arrays To Unmanaged Code Part 3
- Managed and Unmanaged code
- Managed/Unmanaged Code Interoperability
- Managed code and Unmanaged code
- Managed Code and unmanaged Code
- Call Unmanaged DLLs from C#
- 在C#中使用P/Invoke调用Unmanaged Code (1)
- managed code&unmanaged code&native code
- Using Unmanaged Code in C#
- Unmanaged Code's Code Coverage Analyze
- managed code和unmanaged code混合debug
- vc ++.net2005 managed unmanaged mixing code
- An Overview of Managed/Unmanaged Code Interoperability
- Marshaling between Managed and Unmanaged Code
- 创建“维护计划”时遇到的问题
- db2 索引 设计准则
- UltraEdit-32 v14.10 简体中文版
- Visual Studio 2008中的Code Performance Analysis
- Ruby中的二维数组初始化的一个小问题
- Call Unmanaged Code. Part 1 - Simple DLLImport
- Call Unmanaged Code Part 2 - Marshal Class
- 欲擒故纵——我看微软的自由作息时间制度
- Microsoft SQL Server 2000 的数据转换服务
- 1个完整的上传图片的类
- 定时器:为 Windows 实现一个连续更新,高精度的时间供应器
- jsf(一)
- VC点滴
- 创建windows服务