C++封装DLL供C#调用是一种常见的跨语言调用方式,它的主要思想是将C++中的库函数封装成一个动态链接库(DLL),供C#或其他语言调用。下面我会详细介绍如何实现这一过程。
1. 创建一个C++动态链接库
首先,我们需要创建一个C++动态链接库项目。在Visual Studio中,可以通过File->New->Project,然后选择Win32 Console Application,设置项目类型为DLL,选择下一步,最后为项目设置名称和位置。
在项目中添加要封装的C++函数,这里我以一个简单的例子进行说明,代码如下:
// dlltest.h
extern "C"
{
__declspec(dllexport) int add(int a, int b);
}
// dlltest.cpp
int add(int a, int b)
{
return a + b;
}
这里我们定义一个包含add函数的C++库,通过__declspec(dllexport)修饰符将函数导出为DLL外部可调用的函数。
2. 将C++动态链接库封装为C#可调用的DLL
为了使C#能够调用C++动态链接库中的函数,我们需要对C++动态链接库进行封装,使之能够变成C#已知的DLL。
我们可以使用C++/CLI创建一个封装器项目,对C++动态链接库进行封装。在Visual Studio中,可以通过File->New->Project,然后选择CLR Class Library,设置项目名称和位置。
在项目中添加包含C++动态链接库函数的头文件,然后对C++函数进行包装。这里我以一个简单的例子进行说明,代码如下:
// wrapper.h
#pragma once
#include <windows.h>
namespace Wrapper
{
public ref class TestWrapper
{
public:
static int add(int a, int b);
private:
static HMODULE m_hDll;
};
}
// wrapper.cpp
#include "stdafx.h"
#include "wrapper.h"
typedef int (*AddFunc)(int, int);
HMODULE TestWrapper::m_hDll = nullptr;
int TestWrapper::add(int a, int b)
{
if (m_hDll == nullptr)
{
m_hDll = LoadLibraryA("DllTest.dll");
}
AddFunc add = (AddFunc)GetProcAddress(m_hDll, "add");
return add(a, b);
}
上面的代码中,我们首先声明一个TestWrapper类,在该类中声明了一个add函数,对C++动态链接库中的add函数进行了封装。为了实现封装,我们需要通过LoadLibraryA和GetProcAddress函数来获取C++动态链接库中的函数指针,最终使用该指针来调用C++函数。
3. 将C++封装成的DLL引用到C#项目中
经过上述步骤,我们已经成功将C++动态链接库封装成了C#可调用的DLL。现在我们需要在C#项目中引用该DLL,并使用其中的函数。
在Visual Studio中,我们打开我们的C#项目,在解决方案资源管理器中,右键单击“引用”并选择“添加引用”。
在弹出的窗口中,选择“浏览”选项卡,在文件对话框中选择封装后的C++ DLL(.dll)。
在成功添加DLL之后,我们就可以在C#项目中使用封装后的C++函数了。
示例1:调用封装了C++函数的DLL
下面我们来使用一个简单的示例来说明如何在C#项目中调用封装了C++函数的DLL。
首先,我们需要创建一个C#控制台应用程序,在Main函数中添加以下代码:
using System;
using Wrapper;
namespace TestWrapper
{
class Program
{
static void Main(string[] args)
{
int sum = TestWrapper.add(1, 2);
Console.WriteLine(sum);
Console.ReadLine();
}
}
}
在这个例子中,我们使用了TestWrapper类中的add函数,该函数被封装为C#可调用的函数,它会调用封装后的C++函数add来计算1+2的结果。
示例2:将一个C++结构体作为参数传递给C++函数
接下来,我们来看一个更复杂的示例,这个示例中我们将一个C++结构体作为参数传递给C++函数。
首先,我们来定义一个C++结构体:
// dlltest.h
typedef struct
{
int num1;
int num2;
}Param;
extern "C"
{
__declspec(dllexport) int add_param(Param* param);
}
// dlltest.cpp
int add_param(Param* param)
{
return param->num1 + param->num2;
}
在这个示例中,我们定义了一个Param结构体,结构体中包含两个int类型的变量num1和num2。我们还定义了一个add_param函数,该函数接收一个Param指针,并计算num1+num2的结果。
接下来,我们需要对该C++函数进行封装:
// wrapper.h
#pragma once
#include <windows.h>
namespace Wrapper
{
public ref class TestWrapper
{
public:
static int add_param(int num1, int num2);
private:
static HMODULE m_hDll;
};
}
// wrapper.cpp
#include "stdafx.h"
#include "wrapper.h"
typedef int (*AddParamFunc)(void*);
HMODULE TestWrapper::m_hDll = nullptr;
int TestWrapper::add_param(int num1, int num2)
{
if (m_hDll == nullptr)
{
m_hDll = LoadLibraryA("DllTest.dll");
}
AddParamFunc add_param = (AddParamFunc)GetProcAddress(m_hDll, "add_param");
struct Param
{
int num1;
int num2;
}param = { num1, num2 };
return add_param(¶m);
}
在这个示例中,我们定义了一个TestWrapper类,并声明了add_param函数。在add_param函数中,我们首先加载C++ DLL动态链接库,然后使用GetProcAddress函数获取add_param函数的地址,并将参数封装为一个Param结构体类型的指针,最后调用add_param函数并将该结构体指针作为参数传递给C++函数。
接下来,我们可以使用以下代码验证我们的C++函数是否能够正常的使用了Param结构体作为参数传递:
using System;
using Wrapper;
namespace TestWrapper
{
class Program
{
static void Main(string[] args)
{
int sum = TestWrapper.add_param(1, 2);
Console.WriteLine(sum);
Console.ReadLine();
}
}
}
这个示例中,我们首先调用TestWrapper类中的add_param函数,并将1和2作为参数传递给该函数。add_param函数会将这两个参数传递给C++ DLL函数add_param,并计算num1+num2的结果。最终结果应该是3。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C++ 封装 DLL 供 C# 调用详细介绍 - Python技术站