C#直接使用DllImport调用C/C++动态库,dll文件

1.C/C++动态库的编写

下面是我编写的一个比较简单的C++dll文件用来测试,关于如何编写dll文件,我这里便不再赘述,不懂得自行查询,

(1).h文件

#ifdef MYDLL_EXPORTS
#define MYDLL_API __declspec(dllexport)
#else
#define MYDLL_API __declspec(dllimport)
#endif//求两个整数的和(普通类型的参数)
extern "C" MYDLL_API int GetSum(int nNum1, int nNum2);
//获取两个整数中的最大值(含有整数类型的指针为参数)
extern "C" MYDLL_API int GetMaxValue(int *pValue1, int* pValue2);
//获取两个整数中的最小值,最小值以传出参数获取
extern "C" MYDLL_API void GetMinValue(int *pValue1, int* pValue2, int *pMinValue);
//带有char[]与char*参数
extern "C" MYDLL_API int GetLength(char szName[64], char* szBirth);

(2).cpp文件

//求两个整数的和(普通类型的参数)
extern "C" MYDLL_API int GetSum(int nNum1, int nNum2)
{
    return (nNum1 + nNum2);
}

//获取整个整数中的最大值
extern "C" MYDLL_API int GetMaxValue(int *pValue1, int* pValue2)
{
    return (*pValue1 > *pValue2) ? *pValue1 : *pValue2;
}

//获取两个整数中的最小值,最小值以传出参数获取
extern "C" MYDLL_API void GetMinValue(int *pValue1, int* pValue2, int *pMinValue)
{
    if (*pValue1 < *pValue2)
    {
        *pMinValue = *pValue1;
    }
    else
    {
        *pMinValue = *pValue2;
    }
}
//带有char[]与char*参数
extern "C" MYDLL_API int GetLength(char szName[64], char* szBirth)
{
    return (strlen(szName) + strlen(szBirth));
}

2.在C#项目中封装上述库文件为C#接口

上述库文件编译成功后,需要把它拷贝到C#项目的运行目录下,然后代码中使用using System.Runtime.InteropService命名空间即可引用

如果不想直接拷贝,可在C#项目中建立一个文件夹,如名称为Dll,将上述库文件拷贝到此文件夹,然后打开C#项目,点击项目->属性->生成事件中添加copy "$(SolutionDir)Dll\*.dll" "$(TargetDir)此批处理语句。程序编译成功后便会自行将此库文件拷贝到运行目录下

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;

namespace Dll_Test
{
    public class MyDllHelper
    {
        private delegate void CallBackDelegate(int nValue1, int nValue2);
        //接口实现
        public int GetMySum(int num1, int num2)
        {
            return (GetSum(num1, num2));
        }

        public int GetMyMaxValue(IntPtr Value1, IntPtr Value2)
        {
            return GetMaxValue(Value1, Value2);
        }

        public void GetMyMinValue(IntPtr Value1, IntPtr Value2, ref int MinValue)
        {
            GetMinValue(Value1, Value2, ref MinValue);
        }

        public int GetMyLength(string strName, string strBirth)
        {
            return GetLength(strName, strBirth);
        }
  

        [DllImport("MyDll.dll", CallingConvention = CallingConvention.Cdecl)]
        private static extern int GetSum(int num1, int num2);
        [DllImport("MyDll.dll", CallingConvention = CallingConvention.Cdecl)]
        private static extern int GetMaxValue(IntPtr Value1, IntPtr pValue2);
        [DllImport("MyDll.dll", CallingConvention = CallingConvention.Cdecl)]
        private static extern void GetMinValue(IntPtr Value1, IntPtr Value2, ref int MinValue);
        [DllImport("MyDll.dll", CallingConvention =CallingConvention.Cdecl)]
        private static extern int GetLength(string strName, string strBirth);    
    }
}

3.接口实现

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace Dll_Test
{
    class Program
    {
        static void Main(string[] args)
        {
            MyDllHelper myDll = new MyDllHelper();
            Console.WriteLine("两个整数和为:{0}", myDll.GetMySum(10, 10));

            int nValue1 = 10;
            int nValue2 = 50;
            IntPtr ptr1 = Marshal.AllocHGlobal(sizeof(int));
            IntPtr ptr2 = Marshal.AllocHGlobal(sizeof(int));
            
            Marshal.WriteInt32(ptr1, nValue1);
            Marshal.WriteInt32(ptr2, nValue2);
            Console.WriteLine("两个整数中的最大值:{0}", myDll.GetMyMaxValue(ptr1, ptr2));

            int nMinValue = 0;
            myDll.GetMyMinValue(ptr1, ptr2, ref nMinValue);
            Console.WriteLine("两个整数中最大值:{0}", nMinValue);

            Marshal.FreeHGlobal(ptr1);
            Marshal.FreeHGlobal(ptr2);

            string strName = "zhangsan";
            string strBirth = "1993-01-01";
            int nLength = myDll.GetMyLength(strName, strBirth);
            Console.WriteLine("两个字符串的总长度为:{0}", nLength);
     
            Console.ReadKey();
        }
    }
}