項目開發時可能需要調用其動態鏈接庫,如C++動態鏈接庫,實現相應功能,那麼在C#裡怎麼調用C++庫裡的方法呢,如下提供兩種方式。
方式一:建立一個C++項目,選擇dll動態鏈接庫如下。

1 //stdafx.h 文件內容 2 //#ifdef func_api 3 //#else 4 //#define func_api extern "C" __declspec(dllimport) 5 //#endif 6 7 #define func_api extern "C" __declspec(dllexport) 8 func_api double Add1(double x, double y); 9 10 func_api double Sub1(double x, double y); 11 12 func_api double Multiply1(double x, double y); 13 14 func_api double Divide1(double x, double y);
如上定義個宏func_api,用於導出C++項目中函數所定義的標示符__declspec(dllexport),其中extern "C"是作用就是在編譯時用c的方式編譯,也就是不讓函數名字變化,因為用C++編譯器編譯後的函數名稱會變化,如add1編譯後可能是@ILT+575(_Add1)或什麼的不同編譯器不同,為了防止客戶端可以調到這個函數所以用 extern "C" 這樣編譯後的函數名稱就不變了。
1 // ConsoleApplication1.cpp 文件內容: 定義 DLL 應用程序的導出函數。
2 //#define func_api extern "C" __declspec(dllexport)
3 #include "stdafx.h"
4 double Add1(double x, double y)
5 {
6 return x + y;
7 }
8 double Sub1(double x, double y)
9 {
10 return x - y;
11 }
12 double Multiply1(double x, double y)
13 {
14 return x * y;
15 }
16 double Divide1(double x, double y)
17 {
18 return x / y;
19 }
方式二:建立一個C++空項目,選擇dll動態鏈接庫如下。

添加頭文件MathTest.h 代碼如下。
1 #pragma once
2 namespace MathFuncs
3 {
4 class MyMathFuncs
5 {
6 public:
7 // Returns a + b
8 static __declspec(dllexport) double Add(double a, double b);
9
10 // Returns a - b
11 static __declspec(dllexport) double Subtract(double a, double b);
12
13 // Returns a * b
14 static __declspec(dllexport) double Multiply(double a, double b);
15
16 // Returns a / b
17 static __declspec(dllexport) double Divide(double a, double b);
18
19 };
20 }
添加C++文件MathTest.cpp
1 // MathTest.cpp
2 // compile with: /EHsc /LD
3
4 #include "MathTest.h"
5 #include <stdexcept>
6 using namespace std;
7 namespace MathFuncs
8 {
9 double MyMathFuncs::Add(double a, double b)
10 {
11 return a + b;
12 }
13
14 double MyMathFuncs::Subtract(double a, double b)
15 {
16 return a - b;
17 }
18
19 double MyMathFuncs::Multiply(double a, double b)
20 {
21 return a * b;
22 }
23
24 double MyMathFuncs::Divide(double a, double b)
25 {
26 if (b == 0)
27 {
28 throw new invalid_argument("b cannot be zero!");
29 }
30
31 return a / b;
32 }
33 }
添加模塊定義文件,這個文件定義導出函數的名稱,這樣導出的函數名字就不會變了。
LIBRARY ConsoleApplication2 EXPORTS Add @1 Subtract @2 Multiply @3 Divide @4
測試姓名,建立一個C# 控制台項目。

代碼如下。
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Threading.Tasks;
6 using System.Runtime.InteropServices;
7 namespace TestDll
8 {
9 class Program
10 {
11 [DllImport(@"F:\test_project\C++\ConsoleApplication1\Debug\ConsoleApplication1.dll", CallingConvention = CallingConvention.Cdecl)]
12 public static extern double Add1(double x, double y);
13 [DllImport(@"F:\test_project\C++\ConsoleApplication1\Debug\ConsoleApplication1.dll", CallingConvention = CallingConvention.Cdecl)]
14 public static extern double Multiply1(double x, double y);
15
16 [DllImport(@"F:\test_project\C++\ConsoleApplication1\Debug\ConsoleApplication2.dll", CallingConvention = CallingConvention.Cdecl)]
17 public static extern double Add(double x, double y);
18 [DllImport(@"F:\test_project\C++\ConsoleApplication1\Debug\ConsoleApplication2.dll", CallingConvention = CallingConvention.Cdecl)]
19 public static extern double Multiply(double x, double y);
20 static void Main(string[] args)
21 {
22
23 double result = Add1(10, 20);
24 Console.WriteLine("The result of add1 is {0}", result);
25 double result1 = Multiply1(10, 20);
26 Console.WriteLine("The result of Sub1 is {0}", result1);
27 Console.WriteLine("========================================");
28
29
30 double result11 = Add(10, 20);
31 Console.WriteLine("The result of add is {0}", result11);
32 double result111 = Multiply(10, 20);
33 Console.WriteLine("The result of Subtract is {0}", result111);
34 Console.Read();
35
36 }
37 }
38 }

如果想看C++動態鏈接庫是否有函數導出可以用這個工具dumpbin.exe ,默認路徑C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin,很據你vs安裝路徑下找到它,如下。

注:1.extern "C" 不能導出成員函數。
2.使用標准調用方式_stdcall,函數名稱還是會發生改變。
附件鏈接: https://pan.baidu.com/s/1o8RfgIu 密碼: etha