日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
VisualStudio2010調(diào)用非C#編寫(xiě)的DLL文件

背景

目前創(chuàng)新互聯(lián)已為成百上千家的企業(yè)提供了網(wǎng)站建設(shè)、域名、雅安服務(wù)器托管、網(wǎng)站托管運(yùn)營(yíng)、企業(yè)網(wǎng)站設(shè)計(jì)、阿榮網(wǎng)站維護(hù)等服務(wù),公司將堅(jiān)持客戶導(dǎo)向、應(yīng)用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協(xié)力一起成長(zhǎng),共同發(fā)展。

在項(xiàng)目過(guò)程中,有時(shí)候你需要調(diào)用非C#編寫(xiě)的DLL文件,尤其在使用一些第三方通訊組件的時(shí)候,通過(guò)C#來(lái)開(kāi)發(fā)應(yīng)用軟件時(shí),就需要利用DllImport特性進(jìn)行方法調(diào)用。本篇文章將引導(dǎo)你快速理解這個(gè)調(diào)用的過(guò)程。

步驟

1. 創(chuàng)建一個(gè)CSharpInvokeCPP的解決方案:

2. 創(chuàng)建一個(gè)C++的動(dòng)態(tài)庫(kù)項(xiàng)目:

3. 在應(yīng)用程序設(shè)置中,選擇“DLL”,其他按照默認(rèn)選項(xiàng):

***點(diǎn)擊完成,得到如圖所示項(xiàng)目:

我們可以看到這里有一些文件,其中dllmain.cpp作為定義DLL應(yīng)用程序的入口點(diǎn),它的作用跟exe文件有個(gè)main或者WinMain入口函數(shù)是一樣的,它就是作為DLL的一個(gè)入口函數(shù),實(shí)際上它是個(gè)可選的文件。它是在靜態(tài)鏈接時(shí)或動(dòng)態(tài)鏈接時(shí)調(diào)用LoadLibrary和FreeLibrary時(shí)都會(huì)被調(diào)用。詳細(xì)內(nèi)容可以參考(http://blog.csdn.net/benkaoya/archive/2008/06/02/2504781.aspx)。

4. 現(xiàn)在我們打開(kāi)CSharpInvokeCPP.CPPDemo.cpp文件:

現(xiàn)在我們加入以下內(nèi)容:

 
 
 
 
  1. // CSharpInvokeCPP.CPPDemo.cpp : 定義 DLL 應(yīng)用程序的導(dǎo)出函數(shù)。 
  2.  // 
  3. #include "stdafx.h" 
  4.  extern "C" __declspec(dllexport) int Add(int x, int y) 
  5.  { 
  6.  return x + y; 
  7.  extern "C" __declspec(dllexport) int Sub(int x, int y) 
  8.  { 
  9.  return x - y; 
  10.  } 
  11.  extern "C" __declspec(dllexport) int Multiply(int x, int y) 
  12.  return x * y; 
  13.  extern "C" __declspec(dllexport) int Divide(int x, int y) 
  14.  { 
  15. return x / y; 

extern "C" 包含雙重含義,從字面上即可得到:首先,被它修飾的目標(biāo)是“extern”的;其次,被它修飾的目標(biāo)是“C”的。而被extern "C"修飾的變量和函數(shù)是按照C語(yǔ)言方式編譯和連接的。

__declspec(dllexport)的目的是為了將對(duì)應(yīng)的函數(shù)放入到DLL動(dòng)態(tài)庫(kù)中。

extern "C" __declspec(dllexport)加起來(lái)的目的是為了使用DllImport調(diào)用非托管C++的DLL文件。因?yàn)槭褂肈llImport只能調(diào)用由C語(yǔ)言函數(shù)做成的DLL。

5. 編譯項(xiàng)目程序,***在Debug目錄生成CSharpInvokeCPP.CPPDemo.dll和CSharpInvokeCPP.CPPDemo.lib

我們用反編譯工具PE Explorer查看下該DLL里面的方法:

可以發(fā)現(xiàn)對(duì)外的公共函數(shù)上包含這四種“加減乘除”方法。

6. 現(xiàn)在來(lái)演示下如何利用C#項(xiàng)目來(lái)調(diào)用非托管C++的DLL,首先創(chuàng)建C#控制臺(tái)應(yīng)用程序:

7. 在CSharpInvokeCSharp.CSharpDemo項(xiàng)目上新建一個(gè)CPPDLL類,編寫(xiě)以下代碼:

 
 
 
 
  1.  public class CPPDLL 
  2.  { 
  3.  [DllImport("CSharpInvokeCPP.CPPDemo.dll")] 
  4. public static extern int Add(int x, int y); 
  5.  [DllImport("CSharpInvokeCPP.CPPDemo.dll")] 
  6. public static extern int Sub(int x, int y); 
  7. [DllImport("CSharpInvokeCPP.CPPDemo.dll")] 
  8.  public static extern int Multiply(int x, int y); 
  9. [DllImport("CSharpInvokeCPP.CPPDemo.dll")] 
  10.  public static extern int Divide(int x, int y); 
  11.  } 

DllImport作為C#中對(duì)C++的DLL類的導(dǎo)入入口特征,并通過(guò)static extern對(duì)extern “C”進(jìn)行對(duì)應(yīng)。

8. 另外,記得把CPPDemo中生成的DLL文件拷貝到CSharpDemo的bin目錄下,你也可以通過(guò)設(shè)置【項(xiàng)目屬性】->【配置屬性】->【常規(guī)】中的輸出目錄:

這樣編譯項(xiàng)目后,生成的文件就自動(dòng)輸出到CSharpDemo中了。

9. 然后在Main入口編寫(xiě)測(cè)試代碼:

 
 
 
 
  1.  static void Main(string[] args) 
  2.  int result = CPPDLL.Add(10, 20); 
  3.  Console.WriteLine("10 + 20 = {0}", result); 
  4. result = CPPDLL.Sub(30, 12); 
  5.  Console.WriteLine("30 - 12 = {0}", result); 
  6. result = CPPDLL.Multiply(5, 4); 
  7.  Console.WriteLine("5 * 4 = {0}", result); 
  8.  result = CPPDLL.Divide(30, 5); 
  9.  Console.WriteLine("30 / 5 = {0}", result); 
  10.  Console.ReadLine(); 
  11.  } 

運(yùn)行結(jié)果:

方法得到調(diào)用。

10. 以上的方法只能通過(guò)靜態(tài)方法對(duì)于C++中的函數(shù)進(jìn)行調(diào)用。那么怎樣通過(guò)靜態(tài)方法去調(diào)用C++中一個(gè)類對(duì)象中的方法呢?現(xiàn)在我在CPPDemo項(xiàng)目中添加一個(gè)頭文件userinfo.h:

 
 
 
 
  1.  class UserInfo { 
  2. private: 
  3. char* m_Name; 
  4.  int m_Age; 
  5.  public: 
  6. UserInfo(char* name, int age) 
  7.  { 
  8.  m_Name = name; 
  9.  m_Age = age; 
  10.  } 
  11.  virtual ~UserInfo(){ } 
  12. int GetAge() { return m_Age; } 
  13. char* GetName() { return m_Name; } 
  14.  }; 

在CSharpInvokeCPP.CPPDemo.cpp中,添加一些代碼:

 
 
 
 
  1.  #include "malloc.h" 
  2.  #include "userinfo.h" 
  3. typedef struct { 
  4. char name[32]; 
  5.  int age; 
  6. } User; 
  7.  UserInfo* userInfo; 
  8. extern "C" __declspec(dllexport) User* Create(char* name, int age) 
  9.  { 
  10.  User* user = (User*)malloc(sizeof(User)); 
  11.  userInfo = new UserInfo(name, age); 
  12. strcpy(user->name, userInfo->GetName()); 
  13.  user->age = userInfo->GetAge(); 
  14. return user; 
  15.  } 

這里聲明一個(gè)結(jié)構(gòu),包括name和age,這個(gè)結(jié)構(gòu)是用于和C#方面的結(jié)構(gòu)作個(gè)映射。

注意:代碼中的User*是個(gè)指針,返回也是一個(gè)對(duì)象指針,這樣做為了防止方法作用域結(jié)束后的局部變量的釋放。

strcpy是個(gè)復(fù)制char數(shù)組的函數(shù)。

11. 在CSharpDemo項(xiàng)目中CPPDLL類中補(bǔ)充代碼:

 
 
 
 
  1. [DllImport("CSharpInvokeCPP.CPPDemo.dll")] 
  2. public static extern IntPtr Create(string name, int age); 
  3.  [StructLayout(LayoutKind.Sequential)] 
  4.  public struct User 
  5.  { 
  6. [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] 
  7. public string Name; 
  8. public int Age; 
  9.  } 

其中這里的結(jié)構(gòu)User就和C++中的User對(duì)應(yīng)。

12. 在Program.cs中補(bǔ)充代碼:

 
 
 
 
  1.  IntPtr ptr = CPPDLL.Create("李平", 27); 
  2.  CPPDLL.User user = (CPPDLL.User)Marshal.PtrToStructure(ptr, typeof(CPPDLL.User)); 
  3. Console.WriteLine("Name: {0}, Age: {1}", user.Name, user.Age); 

注意:紅色字體部分,這里結(jié)構(gòu)指針首先轉(zhuǎn)換成IntPtr句柄,然后通過(guò)Marshal.PtrToStructrue轉(zhuǎn)換成你所需要的結(jié)構(gòu)。

運(yùn)行結(jié)果:


分享文章:VisualStudio2010調(diào)用非C#編寫(xiě)的DLL文件
文章位置:http://m.5511xx.com/article/cdiegog.html