用VC++基于MFC动态链接库(dll)开发绘图组件,那么C#和VC++分别怎么使用dll?
一、VC DLL接口定义以开发浮云绘图组件FYDC.dll为例,FYDC.dll是VC MFC动态链接库,有多个类库组成,其中包含MFC类和窗体、图标等资源。编码定义及过程如下:
1. 创建MFC常规动态链接库dll工程FYDC;
2. 实现CSLine画线、CSEllipse画圆等类,实现画布CCanvasWnd等所有绘图功能;
3. 在FYDC.h和FYDC.cpp添加绘图类库头文件,如CanvasWnd.h, SLine.h等;
4. 在FYDC.cpp定义导出接口(部分接口如下),并并实现。
1> extern "C" __declspec(dllexport) CCanvas* New()
2> extern "C" __declspec(dllexport) void Create(CCanvas* canvas, HWND hParentWnd, int x, int y, int w, int h)
3> extern "C" __declspec(dllexport) void Load(CCanvas* canvas, const char* fileName)
4> extern "C" __declspec(dllexport) int GetCount(CCanvas* canvas)
5> extern "C" __declspec(dllexport) CSLine* GetAt(CCanvas* canvas, int index)
6> extern "C" __declspec(dllexport) void GetName(CSLine* line, wchar_t* name)
7> extern "C" __declspec(dllexport) void GetSize(CCanvas* canvas, int& width, int& height)
5. 编译生成FYDC.dll和FYDC.lib,即完成dll开发,以供第三方工程复用。
二、C#使用dll详细步骤1. 新建C#工程,复制FYDC.dll到生成的exe目录;
2. 在C#代码文件,添加FYDC.dll导入函数声明。与上面7个导出函数对应的C#版导入函数声明如下:
1> [DllImport("FYDC.dll", EntryPoint = "New", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr New();
2> [DllImport("FYDC.dll", EntryPoint = "Create", CallingConvention = CallingConvention.Cdecl)]
public static extern void Create(IntPtr canvas, IntPtr hParentWnd, int x, int y, int w, int h);
3> [DllImport("FYDC.dll", EntryPoint = "Load", CallingConvention = CallingConvention.Cdecl)]
public static extern void Load(IntPtr canvas, string fileName);
4> [DllImport("FYDC.dll", EntryPoint = "GetCount", CallingConvention = CallingConvention.Cdecl)]
public static extern int GetCount(IntPtr canvas);
5> [DllImport("FYDC.dll", EntryPoint = "GetAt", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr GetAt(IntPtr canvas, int index);
6> [DllImport("FYDC.dll", EntryPoint = "GetName", CallingConvention = CallingConvention.Cdecl)]
public static extern void GetName(IntPtr line, ref byte title);
7> [DllImport("FYDC.dll", EntryPoint = "GetSize", CallingConvention = CallingConvention.Cdecl)]
public static extern void GetSize(IntPtr canvas, ref int width, ref int height);
DLL导出函数类型 对应 C#导入函数类型
函数返回值 CCanvas* 函数返回值 IntPtr
函数形参 CSLine* 函数形参 IntPtr
函数形参 HWND 函数形参 IntPtr
函数返回值或形参 int 函数返回值或形参 int
函数形参 &int 函数形参 ref int
函数形参 const char* 函数形参 string
函数形参 char* 函数形参 ref byte
注意:当函数dll形参时传出字符串时,字符串需要深拷贝,才能正确返回给C#
DLL返回字符串函数实现如下:
extern "C" __declspec(dllexport) void GetName(CSLine* line, char* name)
{
if (shape != line)
{
CString s = line->GetName();
char attr[200];
memset(attr, 0, sizeof(attr));
memcpy(attr, s.GetBuffer(), s.GetLength());
memcpy(name, attr, sizeof(attr));
}
}
在C#项目中,正确使用该接口示例如下:
byte[] s = new byte[200];
lock (s)
{
GetName(shape, ref s[0]);
}
string sName = System.Text.Encoding.Default.GetString(s, 0, s.Length);
sName = sName.Substring(0, sName.IndexOf(''));
当C#读取dll中文是乱码时,是因为双方编码约定未统一,此时应该:
① dll工程设置为多字节编码
②dll接口实现char*改成wchar_t*,并且调用MultiByteToWideChar函数转码
③C#导入函数形参不变,只需转码时Encoding.Default改成Encoding.Unicode
3. 在其他C#代码文件里直接引用此处的导出函数既可。
三、VC使用dll详细步骤1. 新建VC++工程,复制FYDC.dll到生成的exe目录,并复制FYDC.lib到工程源码目录(不是exe目录);
2. 在VC代码文件,添加#pragma comment(lib,"FYDC.lib"),增加新类型导出声明,以及函数导出声明。与上面7个导出函数对应的C#版导入函数申明如下:
#pragma comment(lib,"FYDC.lib")
extern "C" __declspec(dllimport) class CCanvas;
extern "C" __declspec(dllimport) class CSLine;
1> extern "C" __declspec(dllimport) CCanvas * New();
2> extern "C" __declspec(dllimport) void Create(CCanvas * canvas, HWND hParentWnd, int x, int y, int w, int h);
3> extern "C" __declspec(dllimport) void Load(CCanvas* canvas, const char* fileName);
4> extern "C" __declspec(dllimport) int GetCount(CCanvas* canvas);
5> extern "C" __declspec(dllimport) CSLine* GetAt(CCanvas* canvas, int index);
7> extern "C" __declspec(dllimport) void GetName(CSLine* line, char* name);
7> extern "C" __declspec(dllimport) void GetSize(CCanvas* canvas, int& width, int& height);
因为dll就是C++写的,那么VC工程引用的导出函数声明,是一样的。
3. 在VC代码文件直接调用已声明的dll的函数。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)