C#调用C封装的DLL文件

闲言少叙,上干货。

1、创建Win32项目,文件->新建->项目->Visual C+±>Win32空项目->下一步->(勾选DLL,空项目)完成->新建项目->生成.cpp文件
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
2、生成的.cpp文件里的内容即需要封装的函数,注意封装函数的命名比较特殊。

extern "C" _declspec(dllexport)int add(int a, int b)//注意,封装函数的命名比较特殊。

在这里插入图片描述
3、.cpp文件内的函数完成后,右键项目,重新生成。运行完成后会提示生成DLL文件位置。
在这里插入图片描述
----------------------------------------------------------我是分割线
以上就是封装C的DLL文件流程,以下内容就是在C#中调用DLL文件的流程。

1、首先一定要添加引用,必须添加,不然DllImport报错。

using System.Runtime.InteropServices;

2、在namespace里创建一个类

    class CPPDLL
    {
        [DllImport("C8.dll", CharSet = CharSet.Ansi)] //引入dll,并设置字符集    
        public static extern int add(int a, int b);
    }

CPPDLL类位置容易出错,以下是创建该类的具体位置。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;  //必须添加,不然DllImport报错namespace dllConsoleApplication1{  class CPPDLL  {    [DllImport("MyDLL.dll", CharSet = CharSet.Ansi)] //引入dll,并设置字符集    public static extern inProgram.cs代码如下using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Runtime.InteropServices;  //必须添加,不然DllImport报错


namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
    }
    class CPPDLL
    {
        [DllImport("C8.dll", CharSet = CharSet.Ansi)] //引入dll,并设置字符集    
        public static extern int add(int a, int b);
    }

}

3、将生成好的DLL文件拷贝到C#项目debug文件路径下,如D:\Documents\Visual Studio 2013\Projects\C8\WindowsFormsApplication1\bin\Debug
在这里插入图片描述
4、右键C#项目里面的引用,点击添加引用。随后点击浏览,找到C#项目debug路径下的DLL文件进行添加。最后可以在引用里看到添加的DLL文件。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
5、在需要调用封装函数的位置通过CPPDLL.函数名(参数)即可。

            int sum = CPPDLL.add(500, 20);

6、需要注意的是,有的时候传入封装好的函数的参数需要一定格式化。

VC++中主要字符串类型为:LPSTR,LPCSTR, LPCTSTR, string, CString, LPCWSTR, LPWSTR等
但转为C#类型却不完全相同。

主要有如下几种转换:

将string转为IntPtr:IntPtr System.Runtime.InteropServices.Marshal.StringToCoTaskMemAuto(string)

将IntPtr转为string:string System.Runtime.InteropServices.MarshalPtrToStringAuto(IntPtr)

类型对照:

BSTR --------- StringBuilder

LPCTSTR --------- StringBuilder

LPCWSTR --------- IntPtr

handle---------IntPtr

hwnd-----------IntPtr

char *----------string

int * -----------ref int

int &-----------ref int

void *----------IntPtr

unsigned char *-----ref byte

Struct需要在C#里重新定义一个Struct

CallBack回调函数需要封装在一个委托里,delegate static extern int FunCallBack(string str);

注意在每个函数的前面加上public static extern +返回的数据类型,如果不加public ,函数默认为私有函数,调用就会出错。

详情参考:https://blog.csdn.net/jiangxinyu/article/details/7848015

typedef unsigned long int—UInt32
unsigned char*—ref byte(使用byte[]创建数组,在函数中使用ref KeyK[0],具体代码如下)

//C#项目里代码段
byte[] KeyK = new byte[16];
CPPDLL.InitialKey(ref KeyK[0], b);
public static extern void InitialKey(ref byte KeyK, int b);
//C项目里代码段
void InitialKey(unsigned char* KeyK, int b)

------------------------------------------------------我再咯咯咯咯咯咯
以下是bug解决办法
在这里插入图片描述
出现此类bug通过右键项目->属性->生成->目标平台->X86,然后重新运行即可。
在这里插入图片描述

一般报错的几种情况:
1、未将DLL文件正确拷贝到C#项目下bin/debug/路径下。
2、未将C#项目目标平台修改为X86。
3、未将C项目中公共语言运行时支持修改为公共语言运行时支持(/clr),具体操作右键C项目->属性->配置属性->常规->项目默认值->公共语言运行时支持->公共语言运行时支持(/clr)

4、在C#项目中引用DLL文件时注意语句
[DllImport("CC1.dll", EntryPoint = "InitialKey", CallingConvention = CallingConvention.Cdecl)] //引入dll,并设置字符集,其中CC1.dll为需要引用的DLL,InitialKey为该DLL文件中需要调用的函数名。
public static extern void InitialKey(ref byte KeyK, int b);//此类声明参照DLL里面的函数,需要注意的地方是函数中传参的类型需要结合C#微调。
发布了25 篇原创文章 · 获赞 28 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/qq_30680871/article/details/101619769