`
usiboy
  • 浏览: 27000 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

解开VC++调用.Net DLL的神秘面纱

阅读更多

这段时间有个项目是需要使用vc++的程序访问.Net的类,在网上搜过很多文章,大致有两个方法:

    将.Net程序编译成COM,并让C++代码访问COM组件进行调用。

    另一个方法使用CRL编译选项,让.Net代码在CRL(公共运行语言)中管理,这样c++就可以方便的引用.Net的对象。

C++是属于非托管类,而.Net是属于托管类。在运行库的控制下执行的代码称作托管代码,相反,在运行库之外运行的代码称作非托管代码。COM 组件、ActiveX 接口和 Win32 API 函数都是非托管代码的示例。而.Net则属于托管类。微软的产品中这些不同的代码之间都是可以交互的,接下来我将结合实例讲解,此篇文章讲述第二种方式,使用CRL。对于COM的方式稍麻烦一点,如果有兴趣可以查看一下MSDN,地址是:

        COM Interop Tutorials

        与非托管代码交互操作

 

使用VS 2003编写DLL

首先我们创建一个Visual C++项目,创建“类库(.Net)”模板类型,项目名称为“Library”。

创建完了之后你将会看到项目属性中->常规->使用托管扩展,值为“是”,这个选项勾上以后,将按照/crl编译。在VS项目的资源管理器中,将会引用两个.Net库,System.dllSystem.Data.dll ,但是这样还不够,因为需要有.Net lib支持,比较方便一点的是在引用中增加“mscorlib”库,这样项目编译时将默认加入这个库进行编译。

接下来先编写Library.h,增加一个DLL Function

// Library.h

extern "C"
{
	 __declspec(dllexport) int __stdcall Sum(int a,int b);
}
 

然后实现这个头文件,实现的文件名为Library.cpp。

 

// 这是主 DLL 文件。

#include "stdafx.h"

#include "Library.h"

#pragma comment(lib , "msvcrtd.lib")

using namespace System;

BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
					 )
{
    return TRUE;
}

int __stdcall Sum(int a,int b)
{
	Console::WriteLine("It's in method of Sum");
	System::Text::StringBuilder *sb = new System::Text::StringBuilder();
	sb->Append(a);
	sb->Append(" + ");
	sb->Append(b);
	sb->Append(" = ");
	sb->Append(a + b);
	Console::WriteLine(sb->ToString());
	return a + b;
}

 Sum方法使用了两个.Net类,使用.Net的System.Console输出打印的数据,并使用StringBuilder帮助我们增加字符串。VS 2005以上的版本的写法和2003略有不同,2005将这种引用视为特殊的指针类型,那么这个时候的指针不是用‘*’,而是'^',new变成了gcnew

System::Text::StringBuilder ^sb = gcnew System::Text::StringBuilder();
	sb->Append(a);
	sb->Append(" + ");
	sb->Append(b);
	sb->Append(" = ");
	sb->Append(a + b);

 接下来我们就可以编译他了,编译成功之后,可以使用一个Visual C++创建的项目调用它。

 

关于“Library error LNK2020: 无法解析的标记(0A00001C) _CxxThrowException”的问题

这个异常在/crl编译的选项中经常出现,对此我困惑了很久,因为我在项目中使用到了VC++的一些io类,只要使用了他编译的时候就报这个错误,有时也会不使用io类也会出现这个问题,分析看来是缺少某些文件。经过网上的漫长搜索,终于发现,这个是托管扩展在Debug管理器中出现的一些问题,所以需要手动的加入msvcrtd.lib,msvcrtd.dll是微软编译程序调试版本相关文件。加入以后就没问题了。

 

关于源代码

本人上传的源代码只供学习参考使用,希望也有和我一样刚接触此技术的朋友能够顺利的夸过这一难关,希望他能给各位节省不少的时间,同时也为我自己总结一下经验。

源代码包含两部分,Library是用VS 2003创建的DLL .Net模板的项目。

InvokeLibrary是用VC++ 2006创建的Console项目,用来调用Library.dll的测试代码。

参考资料

CLR 控制台应用程序模板 (C++)  --  MSDN Library

 

 

 

1
1
分享到:
评论
2 楼 usiboy 2010-01-02  
kimmking 写道
引用
首先我们创建一个Visual C++项目,创建“类库(.Net)”模板类型,项目名称为“Library”。

创建完了之后你将会看到项目属性中->常规->使用托管扩展,值为“是”,这个选项勾上以后,将按照/crl编译。


你这是直接使用托管的vc++.net

引用
C++是属于非托管类,

也不尽然。


当然,在这里没有一个非常明确的概念去表示c++与.Net之间的区别,问题是在于微软希望将所有的对象都能够统一的放到一个地方进行管理,这个地方就是目前的CLR(Common Language Runtime),现在.Net的所有对象都将放入到此域中进行管理,而c++是在Windows 库函数中运行,所以为了支持在CLR中运行,必须让他扩展成为一个支持CLR中的接口。所以VS编译的c++是需要.Net平台支持,即使这样也不会影响其他程序调用此c++代码只需要安装.Net平台即可。
1 楼 kimmking 2009-12-29  
引用
首先我们创建一个Visual C++项目,创建“类库(.Net)”模板类型,项目名称为“Library”。

创建完了之后你将会看到项目属性中->常规->使用托管扩展,值为“是”,这个选项勾上以后,将按照/crl编译。


你这是直接使用托管的vc++.net

引用
C++是属于非托管类,

也不尽然。

相关推荐

Global site tag (gtag.js) - Google Analytics