刚开始参加一个项目,工程的代码以前的人已经写得差不多了。GUI是用C#写的,底层调用的是C++的DLL。
C++的DLL工程里面全都是些C语言的函数而已,单纯的从DLL中导出再对应到一个C#的类里面。实在很难接受这样子的设计,美其名曰C#是一个比C++更简单纯面向对象的语言,好像他们真正的明白面向对象是什么一样,可是底层还是要用C++,让人气不过的就是其实用的是C语言。这是什么样子的设计,是面向对象的设计吗?那么多的底层DLL工程代码全都是用C语言写的函数而已。如此多的核心代码都是用C语言写的,可以想象这个工程会多么的难以维护;我只是一个初级的程序员,这样的代码我看着就是想吐。
可能是有一点很恶心,C#好像是不可能直接使用用C++所写的类,可是我们也还是有办法做到让C#本质上还是使用的用C++代码产生的对象的。在DLL里面我们只是简单的用一些导出的接口函数让C#使用,而这个DLL内部本质上还是用一个(或者多个,还可以是一个类系统)对象来维护的。可是他们就是不愿意这样子做,让我们现在的工作很难进行,写的代码不能入目。
下面是我写的一个简单的例子程序,虽然这个没有什么,可是看起来心里舒服多了。
一、用VS2005建立一个解决方案unlearn
二、在解决方案unlearn中添加一个VC++的Win32 DLL工程CppDLL
三、添加头文件MyClass.h 内容入下:
1
#ifndef __MYCLASS_H__
2
#define __MYCLASS_H__
3![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
4
#include <iostream>
5
#include <string>
6![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
7
using namespace std;
8![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
9
class CMyClass
10![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif)
{
11
public:
12
CMyClass(string name)
13![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
14
if (name.size() <= static_cast<size_t>(0))
15![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
16
objName = "noname";
17
}
18
objName = name;
19
}
20![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
21
void PrintName()
22![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
23
cout << objName << endl;
24
}
25![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
26
bool MallocString(char *&pStr, int &size)
27![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
28
pStr = new char[5];
29
pStr[0] = 'a';
30
pStr[1] = 'b';
31
pStr[2] = 'c';
32
pStr[3] = 'd';
33
pStr[4] = '\0';
34
size = 5;
35
return true;
36
}
37![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
38
bool FreeString(char *&pStr)
39![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
40
if (pStr == 0)
41![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
42
return false;
43
}
44
cout << pStr << endl;
45
delete []pStr;
46
pStr = 0;
47
return true;
48
}
49![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
50
private:
51
string objName;
52
};
53![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
54
#endif // __MYCLASS_H__
三、添加头文件ExportFunc.h 内容如下:
1
#ifndef __EXPORTFUNC_H__
2
#define __EXPORTFUNC_H__
3![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
4
#include "MyClass.h"
5![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
6
bool CreateObj(char *name);
7
bool DeleteObj();
8
void OperateObj();
9
bool CreateString(char *&pStr, int &size);
10
bool FressString(char *&pStr);
11![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
12
#endif // __EXPORTFUNC_H__
13![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
14
四、添加源文件ExportFunc.cpp 内容如下:
15![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
16
#include "stdafx.h"
17
#include "ExportFunc.h"
18![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
19
CMyClass *pObj = NULL;
20![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
21
bool CreateObj(char *name)
22![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif)
{
23
DeleteObj();
24
pObj = new CMyClass(string(name));
25
return true;
26
}
27![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
28
bool DeleteObj()
29![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif)
{
30
if (pObj != NULL)
31![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
32
delete pObj;
33
pObj = NULL;
34
}
35
return true;
36
}
37![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
38
void OperateObj()
39![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif)
{
40
if (pObj == NULL)
41![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
42
return ;
43
}
44
pObj->PrintName();
45
}
46![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
47
bool CreateString(char *&pStr, int &size)
48![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif)
{
49
if (pObj == NULL)
50![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
51
return false;
52
}
53
return pObj->MallocString(pStr, size);
54
}
55![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
56
bool FressString(char *&pStr)
57![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif)
{
58
if (pObj == NULL)
59![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
60
return false;
61
}
62
return pObj->FreeString(pStr);
63
}
四、添加模块定义文件CppDll.def 内容如下:
1
LIBRARY "CppDll"
2
EXPORTS
3
CreateObj
4
DeleteObj
5
OperateObj
6
CreateString
7
FressString
五、在项目属性设置默认
六、在解决方案unlearn中添加一个C#的控制台应用程序项目CSApp
七、项目属性->生成->输出路径改为"..\debug\" (其实就是让两个项目的输出结果放在一个地方,debug版本C++工程默认的输出路径是这个)
八、修改Program.cs文件 内容如下:
1
using System.Runtime.InteropServices;
2![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
3
namespace CSApp
4![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif)
{
5
class TestDll
6![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
7
[DllImport("CppDll.dll", CharSet = CharSet.Ansi)]
8
public static extern bool CreateObj(string name);
9
[DllImport("CppDll.dll", CharSet = CharSet.Ansi)]
10
public static extern bool DeleteObj();
11
[DllImport("CppDll.dll", CharSet = CharSet.Ansi)]
12
public static extern void OperateObj();
13
[DllImport("CppDll.dll", CharSet = CharSet.Ansi)]
14
public static extern bool CreateString(out IntPtr pStr, out int size);
15
[DllImport("CppDll.dll", CharSet = CharSet.Ansi)]
16
public static extern bool FressString(out IntPtr pStr);
17
}
18![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
19
class Program
20![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
21
static void Main(string[] args)
22![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
23
IntPtr pStr = IntPtr.Zero;
24
int size = 0;
25
TestDll.CreateObj("huymou");
26
TestDll.OperateObj();
27
TestDll.CreateString(out pStr, out size);
28
TestDll.FressString(out pStr);
29
TestDll.DeleteObj();
30
}
31
}
32
}
把CSApp设为启动工程就可以了。这个例子很简单,C#只是简单调用了DLL中的几个导出的接口函数,它们其实没有做什么,就有CreateObj和DeleteObj很重要,其它的函数只是简单的把CMyClass的公共成员函数包了一下。这样子就可以用C#使用C++所写的类了,我们核心的代码还是用面向对象的方法来实现的,而且本质上我们是用了对象来帮助我们做事的。
当然可能本人见识不够,不知道还有更好的办法,现在我也是刚刚想到这些的,好多都可以完善。最后还是一句话,我永远喜欢C++,我相信C++可以做得更好、更出色,不想看到乱用C++的事情出现;有些人乱用了C++,还说C++一大堆的坏话。真正大型的工程其实C++才是最适合的。