需求
在日常开发中,偶然间就会使用C/C++编写的动态链接库。那么如何在C#中调用和使用C/C++动态链接库的函数呢?
Melphi使用C/C++编写了一个AddCount()方法,用于计算两个传入参数的和,并返回给调用者。
环境
Windows 10
Visual Studio 2017
平台工具集:Visual Studio 2017 (v141)
实现
C/C++动态链接库
-
新建一个动态链接库的项目,命名为
Melphi.Test
- 打开新建的项目,添加
Melphi.Test.h
头文件
- 打开
Melphi.Test.h
头文件,并添加我们的Add
函数,代码如下:
#pragma once
// 宏定义:说明通过 MelphiAPI 声明的函数为导出函数,供其他程序调用,作为动态库的对外接口函数
#define MelphiAPI _declspec(dllexport) _stdcall
// 传递两个参数(int),获取计算的结果(int)
extern "C" int MelphiAPI Add(int a, int b);
- 打开
Melphi.Test.cpp
文件,添加Add
函数的实现,代码如下:
// Melphi.Test.cpp : 定义 DLL 应用程序的导出函数。
//
#include "stdafx.h"
#include "MelphiTest.h"
// 获取两个 int 值的和
int MelphiAPI Add(int a, int b)
{
return a + b;
}
到此,我们的动态链接库的函数就写好了,接下来,我们使用我们熟悉的C#来调用这个函数。
C# DllImport
为了方便我们代码的管理,我们将所有的导入函数都统一定义到DllImportCore.cs
的文件中。
C#当然不能直接使用动态链接库中的函数,我们需要通过.NETFramework里面提供的DllImport
来帮我制造
一个连接动态链接库中函数的入口点,需要使用到的命名空间:System.Runtime.InteropServices
- 函数入口的声明定义,代码如下:
using System;
using System.Runtime.InteropServices;
using System.Text;
namespace Melphi
{
public class DllImportCore
{
/// <summary>
/// 求和 传入参数(C++ int == C# int)
/// </summary>
/// <param name="a"></param>
/// <param name="b"></param>
/// <returns></returns>
[DllImport("cpplib/Melphi.Test.dll", EntryPoint ="Add", CallingConvention = CallingConvention.StdCall)]
public static extern int Add(int a, int b);
}
}
- DllImport中参数说明
cpplib/Melphi.Test.dll
:表示我们动态链接库的 DLL 名称,这里使用了相对路径标识。它是特性DllImportAttribute
的构造器(函数)需要传递和指定的参数,称为定位参数,是强制性的——应用这个特性时,必须指定这个参数。
EntryPoint ="AddCount"
:表示我们定义的函数入口点的名称,也就是动态链接库中我们需要调用函数的名称。它是特性DllImportAttribute
的公共实例字段,它是用于设置字段的参数,称为命名参数,这个参数是可选的——应用这个特性时,不一定要指定参数。
CallingConvention = CallingConvention.StdCall
:指示入口点的调用规约,这里使用默认规约。它是特性的一个命名参数。
-
函数的调用
在我们定义的时候,函数变成静态的函数。因此在调用的时候,按照调用静态方法的形式去调用即可。下面是在WPF中的App类的OnStartup
方法内调用。
using System;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows;
namespace Melphi
{
/// <summary>
/// App.xaml 的交互逻辑
/// </summary>
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
Console.WriteLine("2+2=" + DllImportCore.Add(2, 2));
Console.ReadKey();
}
}
}
And then,the coding work is completed.Next,we will to build and debug it.
运行
在运行之前 ,我们需要编译程序。前面我们知道,C#调用的动态链接库的路径在C#运行程序的当前目录下的cpplib
文件夹中,因此,我们需要将我们的动态链接库编译到该文件夹中(也可以直接编译之后,直接将DLL拷贝过去)。
- 动态链接库的编译属性配置
需要将项目的输出目录修改到我们需要它生成的目标文件夹即可。
操作:项目(Melphi.Test)-->右键-->属性;配置属性-->常规-->输出目录-->浏览--(找到目标文件夹)-->点击确定。
-
生成动态链接库
生成成功之后,可以检查下文件是否成功赋值到我们需要的目录下。
-
F5启动
在启动之前,需要将C#项目Melphi
设为启动项。
由于我们需要看Console
输出的内容,所以需要将项目的属性的输出类型设置为控制台应用程序
。
- 结果
总结
本文主要用于记录如何使用C#调用动态链接库。后续会丰富对各种数据类型的函数调用以及指针的介绍和使用。
Over
每次记录一小步...点点滴滴人生路...