闲言少叙,上干货。
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#微调。
向IT工作者致敬,后丹之喜碧CatBrother欢迎吐槽:
后丹-喜碧CatBrother