c++、C#調用c++dll

可參考:在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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章