询问者
C++/CLI:混合编程中托管调用非托管代码(C++/CLI 调用ANSI/ISO C++)问题(含模板)?

常规讨论
-
背景介绍:
我想在C++/CLI (属.net)程序中使用一些原有的ANSI/ISO C++(以下将称作 Native C++ )代码,以免以前的C++代码浪费。
Native C++代码中,有些是用模板的形式实现的。
我的编程理念、具体实现步骤以及对这种编程方式的几点思考:
编程理念:在C++/CLI 程序中,透过混合编程(C++/CLI和Native C++)方式生成的DLL,去调用Native C++ 中的代码。
混合编程生成的DLL,只是做简单的函数调用,而不做函数实现(即不重写函数方法体,如果那样的话,那就不用使用Native C++代码了)。
具体实现步骤:
1、将Native C++ 代码放入 CLR 的类库中编译生成 Lib 文件(静态库文件)<请注意:此时的代码是纯 ANSI/ISO C++>;
2、新建一个C++/CLI 类库,引入上述Lib文件,编写调用代码,生成DLL文件(动态库文件).<请注意:此时的代码既有C++/CLI,又有ANSI/ISO C++,属混合编程,对于生成的DLL文件,姑且让我们现在叫他.net 引导包,以下也都这么称呼>;
3、新建C++/CLI 窗体程序,引入DLL文件以供使用<请注意:此时的代码是纯C++/CLI >
这个思路应该木有问题吧?ANSI/ISO C++ 可以不用修改就可以在CLR 的类库中编译、生成成功。
我留意到现在很多的硬件都支持C#和VB.net开发,他们都是提供.sys 和一个DLL文件,这种实现应该与我的思维有相似之处吧。
对这种编程方式的几点思考:
1、分这么多文件来处理,一个目的就是方便对代码的管理,知道那部分是纯Native C++,哪部分是混合模式等等,到时候修改也方便;
2、这样也有助于程序效率的提升,尽量减少系统在托管于非托管切换工作中的资源消耗;
3、这里虽然做得是混合编程,但也尽量保障局部地区血统的纯正性,只是非混合不可了我们才混合。当然,更多的考虑是程序效率中切换工程中资源消耗问题。
我的问题:
1、以上的构架思路,哪些地方需要修改一下,以使其更加合理?
2、托管与非托管的相互调用的时候,肯定会因为资源的切换而导致效率损耗的问题,能不能给我一点这方面的概念?
3、在封装.net 包的时候,封装模板经常出问题,具体见下面代码,我该如何解决?
- 已移动 ThankfulHeart 2012年8月17日 5:56 VC++.NET问题 (发件人:.NET Framework 一般性问题讨论区)
- 已更改类型 Damon ZhengModerator 2012年9月3日 6:25
全部回复
-
以下代码都在VS2010中实现。
此部分为第一部分,即Native C++ 部分,能顺利编译并生成 Lib 文件。
----------------------------A。h-----------------------------------------
#pragma once
template< typename Elemtype > // 声明模板类
class Sqlist
{
Protected:
int count; // 指定线性表中当前实际元素个数
int maxSize; // 指定线性表中可容纳的最大元素个数
ElemType *elems; // 元素存储空间
bool Full(); // 判断线性表是否已满
void Init( int size ); // 初始化线性表
Public:
SqList( int size = 20 ); // 构造函数
virtual ~SqList(); // 析构函数模板
int Length(); // 求线性表长度
bool Empty(); // 判断线性表是否为空
void Clear(); // 将线性表清空
}
template <typename ElemType>
SqList<ElemType>::SqList(int size) // 构造函数
{
elems = NULL;
Init(size);
}
template <typename ElemType>
void SqList<ElemType>::Init(int size)
{
this->maxSize = size;
if( elems != NULL )
{
delete []elems;
}
elems = new ElemType[this->maxSize];
this->count = 0;
}
template <typename ElemType>
SqList<ElemType>::~SqList()
{
delete []elems;
}
template <typename ElemType>
int SqList<ElemType>::Length()
{
return this->count;
}
template <typename ElemType>
bool SqList<ElemType>::Empty()
{
return 0 == this->count;
}
template <typename ElemType>
void SqList<ElemType>::Clear()
{
this->count = 0;
}
- 已编辑 qingfy2007 2012年8月17日 6:49
-
此为第二部分,即混合编程部分,照样可以编译生成.DLL文件。所有代码放在《 A.h 》中,关键代码如下:
------------------------------------------A.h---------------------------------------------------------------
#pragma once
#include “A.h” // 引入 Native C++ 头文件
namespace Native // 新建命名空间,方便在工程中引用
{
----
Template<typename Elemtype> // 声明模板,这样做好像不妥,因为不是引入Native C++ 模板,
// 而是重新声明
Public ref class SqList
{
// ========================================这么做事方便对非托管类型的引用;
Private:
::SqList<ElemType>* _native;
public:
SqList<ElemType>* native() { return _native; }
SqList( ::SqList<ElemType>* native ) { _native = native; }
// ==============================================================
SqList()
{
_native = new ::SqList<ElemType>( this->maxSize );
}
~SqList() { delete _native; }
template <typename ElemType>
int Length() { return _native->Length(); }
后面的几个函数都与上面的声明和实现方式相同。
}
}
-
第三部分:引入DLL文件并使用,生成.exe 文件错误。
新建一个窗体程序,之后引入上述DLL文件,关键代码如下:
#pragma once
#include “A.h” // 引入第二部分的头文件
...
using namespace Native; // 引入自定义命名空间;
...
Native::SqList<charsq; LL 中的模板类;
sq = gcnew Native::SqList<char>(12); // 后面的12 表示线性表可以包含的元素容量;
。。。。
编译错误,错误内容: C2872:SqList:不明确的符号(此为唯一的编译错误)。
指向的错误代码所在的行为第一部分(即Native C++部分)的构造和析构函数错误!在第一部分中已经用红色字体标识。
求指点!!!
不胜感激!!!
-
我已经上传了源代码,大家可以下下来看一下。
账号:microsoft000
密码:000microsoft
附件中有整个工作空间(WorkSpace)的源码!我将其分为三个子项目,其中:
NativeCpp:对应第一部分,为纯 Native C++ 源码,生成 .lib 文件,可生成成功;
CLICpp:对应第二部分,为混合编程模式,生成 .DLL 文件,可生成工程;
Test:对应第三部分,在其中引入上述的DLL文件并进行测试,其亦为启动工程,生成.exe文件错误。
下载之后,您需要修改 CLICpp 项目中的库文件目录,因为我在建立工程的时候,使用的是绝对目录,指向的是整个工作空间的DeBug 目录。
-
您好,
首先,非常感谢您的积极参与。
我浏览了您提出的问题,根据我的判断,您的问题很难有一个标准的答案。(除了第三个问题您已经自行解决了。)
所以我认为这个帖子如果改为常规讨论会更好一些,并且我暂且将类型改为常规讨论。
谢谢您的理解和支持。
Damon Zheng [MSFT]
MSDN Community Support | Feedback to us
- 已编辑 Damon ZhengModerator 2012年9月3日 6:26