C#和VC++调用dll详细过程,导出导入函数数据类型对应关系,返回字符串实现方式

用VC++基于MFC动态链接库(dll)开发绘图组件,C#工程如何使用VC dll?C#导入函数数据类型与dll导出数据类型对应关系如何?C#怎么获取dll函数的字符串?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('\0'));

当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的函数。

posted @ 2022-05-21 22:29  浮云绘图  阅读(619)  评论(0编辑  收藏  举报