C#使用過(guò)程中經(jīng)常會(huì)遇到和C++聯(lián)合開(kāi)發(fā)的過(guò)程,通過(guò)C++編寫(xiě)動(dòng)態(tài)庫(kù),封裝成dll后再C#中調(diào)用,在此做個(gè)記錄,并供后期查看
一、新建C#控制臺(tái)項(xiàng)目
打開(kāi)VisualStudio,新建一個(gè)C#控制臺(tái)項(xiàng)目,項(xiàng)目名稱(chēng)HelloWorldTest
點(diǎn)擊下一步,一個(gè)空的默認(rèn)c#項(xiàng)目創(chuàng)建完成
二、創(chuàng)建C++庫(kù)
在解決方案上右鍵--添加--新建項(xiàng)目,建一個(gè)C++動(dòng)態(tài)鏈接庫(kù)工程,輸入項(xiàng)目名稱(chēng)TestDll
創(chuàng)建完成后如下,在源文件--右鍵--新建項(xiàng)--添加C++(.CPP文件),文件內(nèi)容如下:
#include "pch.h"
#include "HelloDll.h"
#include<iostream>
void HelloWorld(char* name)
{
std::cout << "Hello World " << name << std::endl;
}
int Test()
{
return 123456;
}
int Add(int a, int b)
{
return a + b;
}
C++庫(kù)導(dǎo)出有兩種方式,但是最好兩種方式同時(shí)使用,據(jù)說(shuō)第二種是為了防止名字錯(cuò)亂,
1、以C語(yǔ)言接口的方式導(dǎo)出
在頭文件--右鍵--新建項(xiàng),然后新建HelloDll.h頭文件,如下圖
這種方法就是在函數(shù)前面加上 extern "C" __declspec(dllexport)
加上extern "C"后,會(huì)指示編譯器這部分代碼按C語(yǔ)言的進(jìn)行編譯,而不是C++的。
extern "C" __declspec(dllexport) void HelloWorld(char* name);
extern "C" __declspec(dllexport) int Test();
extern "C" __declspec(dllexport) int Add(int a,int b);
2、以模塊定義文件的方式導(dǎo)出
在源文件上點(diǎn)擊右鍵,選擇添加-》新建項(xiàng)
然后選擇代碼-》模塊定義文件
在HelloDll.def中輸入
LIBRARY "HelloDll"
EXPORTS
HelloWorld @ 1
Test @ 2
Add @ 3
EXPORTS下面就是要導(dǎo)出的函數(shù),這里不需要添加分號(hào)隔開(kāi),直接換行就行。
在C#項(xiàng)目中添加引用:同時(shí)把C#代碼修改為:
因?yàn)橐玫紻llImport,所以先導(dǎo)入命名空間using System.Runtime.InteropServices;
注意:在DllImport導(dǎo)入C/C++編寫(xiě)的動(dòng)態(tài)庫(kù)時(shí)函數(shù),可以加上一些約定參數(shù),例如:
[DllImport(@"HelloDll.dll", EntryPoint = "Test", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = false, CallingConvention = CallingConvention.StdCall)]
CallingConvention = CallingConvention.Cdecl,來(lái)指定入口點(diǎn)的調(diào)用約定,否則有可能會(huì) 報(bào)錯(cuò)
因?yàn)镃/C++編寫(xiě)的動(dòng)態(tài)庫(kù)默認(rèn)的入口點(diǎn)約定為_(kāi)cdecl,而VS默認(rèn)調(diào)用動(dòng)態(tài)庫(kù)時(shí)的約定為_(kāi)winapi
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace DllTest
{
internal class Program
{
[DllImport("HelloDll.dll")]
public static extern void HelloWorld(string name);
[DllImport("HelloDll.dll")]
public static extern int Test();
[DllImport("HelloDll.dll")]
public static extern int Add(int a, int b);
static void Main(string[] args)
{
Console.WriteLine(Test().ToString());
Console.WriteLine(Add(2, 5));
HelloWorld("LiLi");
Console.ReadKey();
}
}
}
運(yùn)行程序,結(jié)果如下:
這樣就成功實(shí)現(xiàn)了C#調(diào)用的C++庫(kù)