可參考:在VS2010上使用C#調用非託管C++生成的DLL文件(圖文講解)(已收藏)
- 一、生成C++ dll
(1)新建項目:win32 dll項目DynamicLinkLibrary,解決方案名:dllTest
(2)添加代碼:
Add.h
#pragma once
//#define DLLEXPORT
//#define DLLIMPORT
#if defined(DLLEXPORT)
#define DLLAPI __declspec(dllexport)
#elif defined(DLLIMPORT)
#define DLLAPI __declspec(dllimport)
#endif
extern "C" DLLAPI int Add(int x, int y);// extern "C"很重要
Add.cpp
#include "Add.h"
extern "C" DLLAPI int Add(int x, int y)
{
return x + y;
}
(3)添加預定義DLLEXPORT(或者在Add.cpp開頭中添加#define DLLEXPORT):
(4)編譯生成。
- 二、C++調用dll
(1)添加空的win32控制檯項目dllCall
(2)添加main.cpp文件:
//#include "..\DynamicLinkLibrary\Add.h"
#include <Windows.h>
#include <iostream>
int main()
{
typedef int(*pAdd)(int x, int y);//函數指針
HINSTANCE hHanlde;
hHanlde = LoadLibrary(L"DynamicLinkLibrary.dll");
if (hHanlde)
{
pAdd Add = (pAdd)GetProcAddress(hHanlde, "Add");
if (Add)
{
int value = Add(1, 2);
std::cout << value;
}
FreeLibrary(hHanlde);
}
return 0;
}
(3)編譯生成,運行:
- 三、C#調用C++ dll
此處僅考慮調用C++ dll的函數,如果是C++的類則需要在c#中再定義相應的類。具體查看在VS2010上使用C#調用非託管C++生成的DLL文件(圖文講解)(已收藏),該文章的附加程序:CSharpInvokeCP代碼.rar
(1)添加項目C#控制檯項目dllCallCS;
(2)添加代碼:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
namespace dllCallCS
{
class Program
{
//可將DynamicLinkLibrary.dll複製到項目生成目錄,再採用以下調用:
//[DllImport("DynamicLinkLibrary.dll")]
[DllImport(@"E:\VSproject\dllTest\Debug\DynamicLinkLibrary.dll")]
extern public static int Add(int x, int y);
static void Main(string[] args)
{
int v = Add(1, 2);
Console.WriteLine(v);
Console.ReadLine();
}
}
}
(3)在項目屬性中,設置目標平臺爲x86(此處很重要,要保證與dll的平臺一致,否則產生異常),可參考:試圖加載格式不正確的程序。 (異常來自 HRESULT:0x8007000B)
(4)編譯生成,運行:
代碼:dllTest.rar
- 四、C++調用dll的類
具體得另外調查,這裏僅考慮簡單的情況(可參考:怎樣從一個DLL中導出一個C++類)。
dll代碼與調用是同一編譯器生成纔有效;沒有導出string類型(所以有警告,但調用端依然有效);或許可採用虛函數的實現形式。
(1)給DynamicLinkLibrary添加Person.h:
#pragma once
#if defined(DLLEXPORT)
#define DLLAPI __declspec(dllexport)
#elif defined(DLLIMPORT)
#define DLLAPI __declspec(dllimport)
#endif
#include <string>
using namespace std;
class DLLAPI Person
{
public:
Person(string name, int age) :_name(name), _age(age) {}
string _name;
int _age;
string PersonInfo();
};
添加Person.cpp:
#include "Person.h"
string Person::PersonInfo()
{
char ints[100];
memset(ints, 0, 100);
_itoa(_age, ints, 10);
string agestr = ints;
return string("名字:") + _name + string("\n") + string("年齡:") + agestr;
}
(2)編譯生成,可用Dependency Walker(depends.exe)查看dll導出的函數:
因爲不同編譯器給成員函數命名(name mangling)不一樣,所以調用端不能用其他編譯器。
(3)調用端dllCall的main.cpp修改如下:
#include "..\DynamicLinkLibrary\Add.h"
#include "..\DynamicLinkLibrary\Person.h"
#include <Windows.h>
#include <iostream>
#include <string>
using namespace std;
//#pragma comment(lib,"DynamicLinkLibrary.lib")//如果添加了庫目錄及附加依賴項,此項可註釋
void CallClass()
{
Person person("張三", 20);
string info = person.PersonInfo();
cout << info.c_str();
}
int main()
{
//typedef int(*pAdd)(int x, int y);//函數指針
//HINSTANCE hHanlde;
//hHanlde = LoadLibrary(L"DynamicLinkLibrary.dll");
//if (hHanlde)
//{
// pAdd Add = (pAdd)GetProcAddress(hHanlde, "Add");
// if (Add)
// {
// int value = Add(1, 2);
// std::cout << value;
// }
// FreeLibrary(hHanlde);
//}
CallClass();
return 0;
}
注意添加庫目錄及附加依賴項
(4)編譯生成,運行:
最終代碼:dllTest-最終版.rar