使用C++开发界面,时间效率上来说,不如C#开发的快和方便。但是CTP的库是C++的,并没有C#的库,网上也有人用C#的PINVOKE的方式将C++的函数一个个转换为C#能用的接口,我是看了下,原理ok,但是真心转换起来工作量太大了。
借鉴
swig把CTP转javablog.csdn.net
这篇文章,我想swig转C#这个方式应该更容易,于是今天先写一个demo,然后尝试着转转看。先参考如下的一个基础例子。
swig转C#blog.csdn.net
swig是将C++原始代码,包装成一个方便其他语言调用的工具。
swig转C#主要做两步操作:
- 将C++代码进行一次封装,生成wrap未文件名结尾的C++文件,这些warp文件中会创建一些新的方法,这些新方法是对于开发人员而言是透明的,它们不是给开发人看的,而是给其他语言使用的。生成的dll中包含这些新方法。
- 同时生成C#对应的类文件,这些类文件需要拷贝到C#项目中,这些类对应于原始C++中的类名和方法名,这样就可以做到在C#中访问和原始C++项目中一样的类和方法。 实际上这一步做的工作就是调用上一步产生的wrap中的方法,wrap中的方法再去调用原始C++的方法。
但是现在还有一个问题:
以上C#的例子中,没有继承实现和回调这两种实现。只有解决了这两个问题,才能进一步转换CTP的类库。
首先得解决这个,于是自己在其基础上,按照如下7步骤生成一个可以被C#方便使用的C++的dll。
一、利用Swig生成C#方便使用的DLL
step 1 : 创建了如下项目,一个C++动态链接库的项目,一个C#桌面应用程序。
step 2 :其中c++_file.idl文件内容如下,这个文件是swig转换规则的定义文件,同时,要修改该文件属性,否则项目编译会把该文件也编译进去,会报错的。右键该文件属性:项类型->自定义生成工具。
%module(directors = "1") cppdll /*directors = "1",才可以使用虚函数的多态特性,否则只能继承,不能多态*/
%{
/* 在包装代码中包含头文件 */
#include "c++_file.h"
%}
%feature("director") Addmethod; /*需要指明多态的类,若module(directors = "1")未声明,则此处没有意义*/
/* 解析头文件生成包装代码 */
%include "c++_file.h"
step 3 :c++_file.h
#pragma once
class Addmethod
{
public:
virtual int add(int a, int b) { return 0; };
virtual ~Addmethod() {}
};
class CPlusPlusClass
{
public:
//加法计算实际上是通过Addmethod.add实现
int Add(int a,int b,Addmethod* method);
};
step 4 :C++_project.cpp
// C++_project.cpp: 定义 DLL 应用程序的导出函数。
//
#include "stdafx.h"
#include "c++_file.h"
int CPlusPlusClass::Add(int a, int b,Addmethod* method)
{
if(method)
return method->add(a,b);
else
return a + b;
}
step 5 :以上代码写好后,就可以使用swig进行转换了,命令行切换到项目c++_file.idl所在目录,输入如下命令,(swig已经加到系统的环境变量中才可以直接使用命令,否则需要全路径)
swig -c++ -csharp c++_file.idl
step 6 :运行没有报错,则会生成如下文件,将其中后缀为.cs的文件全部拷贝到C#项目中。
step 7 :在C++_project项目上,会看到debug目录下有生成一个C++_project.dll文件。将该文件拷贝到C#项目的debug目录下。
二、C#使用上述DLL
在C#项目中,使用代码如下:
- 创建子类ChildMethod 继承C++的Addmethod类,并重写方法add
- 创建子类Child类,继承C++中的CPlusPlusClass类,并新增方法showChild
- 调用child对象,并将childMethod对象传入,以便C++的dll库进行多态回调。
class ChildMethod : Addmethod
{
public override int add(int i,int j)
{
return (i+j)*100;
}
}
class Child:CPlusPlusClass
{
public string showChild()
{
return ("child");
}
}
private void button3_Click(object sender, EventArgs e)
{
Addmethod method = new ChildMethod();
Child child = new Child();
richTextBox1.Text += DateTime.Now.ToLongTimeString() + " " + child.Add(3, 3, method)+ "n";
}
总结
整体而言,利用swig封装C++为C#的调用方式,可以极大的减轻工作量,同时方便后续高效率的开发使用原先的C++库。