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

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

新聞中心

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

背景

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

在項目過程中,有時候你需要調用非C#編寫的DLL文件,尤其在使用一些第三方通訊組件的時候,通過C#來開發(fā)應用軟件時,就需要利用DllImport特性進行方法調用。本篇文章將引導你快速理解這個調用的過程。

步驟

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

2. 創(chuàng)建一個C++的動態(tài)庫項目:

3. 在應用程序設置中,選擇“DLL”,其他按照默認選項:

***點擊完成,得到如圖所示項目:

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

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

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

 
 
 
 
  1. // CSharpInvokeCPP.CPPDemo.cpp : 定義 DLL 應用程序的導出函數(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" 包含雙重含義,從字面上即可得到:首先,被它修飾的目標是“extern”的;其次,被它修飾的目標是“C”的。而被extern "C"修飾的變量和函數(shù)是按照C語言方式編譯和連接的。

__declspec(dllexport)的目的是為了將對應的函數(shù)放入到DLL動態(tài)庫中。

extern "C" __declspec(dllexport)加起來的目的是為了使用DllImport調用非托管C++的DLL文件。因為使用DllImport只能調用由C語言函數(shù)做成的DLL。

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

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

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

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

7. 在CSharpInvokeCSharp.CSharpDemo項目上新建一個CPPDLL類,編寫以下代碼:

 
 
 
 
  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#中對C++的DLL類的導入入口特征,并通過static extern對extern “C”進行對應。

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

這樣編譯項目后,生成的文件就自動輸出到CSharpDemo中了。

9. 然后在Main入口編寫測試代碼:

 
 
 
 
  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.  } 

運行結果:

方法得到調用。

10. 以上的方法只能通過靜態(tài)方法對于C++中的函數(shù)進行調用。那么怎樣通過靜態(tài)方法去調用C++中一個類對象中的方法呢?現(xiàn)在我在CPPDemo項目中添加一個頭文件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.  } 

這里聲明一個結構,包括name和age,這個結構是用于和C#方面的結構作個映射。

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

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

11. 在CSharpDemo項目中CPPDLL類中補充代碼:

 
 
 
 
  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.  } 

其中這里的結構User就和C++中的User對應。

12. 在Program.cs中補充代碼:

 
 
 
 
  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); 

注意:紅色字體部分,這里結構指針首先轉換成IntPtr句柄,然后通過Marshal.PtrToStructrue轉換成你所需要的結構。

運行結果:


分享題目:VisualStudio2010調用非C#編寫的DLL文件
網(wǎng)站鏈接:http://www.5511xx.com/article/cdiegog.html