- 浏览: 17024 次
最新评论
C/C++通过COM调用.net托管程序集的实现
2010年06月18日
在.NET托管程序集中,调用非托管的win32 dll 可以通过DllImport 或者Interop中的 P/Invoke 技术将非托管dll生成托管的dll来访问;但反过来,如何在非托管环境下(如C/C++)调用托管的.NET程序集呢?用COM技术就是该问题的一种解决方法:
(1) 首先,创建一个.NET的C# 类库解决方案,并添加两个类,IMyInterface和MyMethods:
接口类 IMyInterface.cs (用于生成COM接口)
using System;
using System.Runtime.InteropServices;
namespace DotNet
{
[Guid("0ED08E85-A627-4894-919C-A404E3420F98")]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
///
/// IMyInterface接口 [提供给C程序调用]
///
public interface IMyInterface
{
int Say(string str);
}
}
Guid的生成用于确定COM的唯一性,在VS.NET2003 开发环境下->工具->创建GUID->Copy-> 替换到上面Guid的值(注意:粘贴板里 形如 0x4c05b60, 0xcda8, 0x4e50, 0xa7, 0x58, 0xcb, 0x9e, 0x5d, 0xb6, 0x9, 0xc5 的值需留到C/C++的代码文件里使用,它和上面的Guid值是一一对应的)
实现类 MyMethods.cs (要调用的托管方法,如果要调用另外的托管程序集,添加程序集引用即可)
using System;
using System.Runtime.InteropServices;
namespace DotNet
{
[Guid("DE21C7D0-CC57-4ed6-AB55-25B4FF8E33F2")]
[ClassInterface(ClassInterfaceType.None)]
///
/// 托管程序集 [内部要实现的功能]
///
public class MyMethods:IMyInterface
{
public static int SayHello(string sInput)
{
Console.WriteLine("托管程序集开始运行......");
Console.WriteLine("非托管环境C传递到托管环境.NET(C#)的字符串是:\r\n{0}",sInput);
return sInput.Length;
}
#region IMyInterface 成员
public int Say(string str)
{
return SayHello(str);
}
#endregion
}
}
该类实现了接口类的相应方法,也需生成Guid值.
(2) 转到 AssemblyInfo.cs:
修改本程序集的版本号,如 [assembly: AssemblyVersion("1.0.0.0")] ,指定版本号用于确定程序集的唯一性,再添加强名称到本程序集,如 [assembly: AssemblyKeyFile("..\\..\\DotNet.snk")]
在.NET SDK 命令行下生成 强名称文件如下:
sn -k DotNet.snk
(3) 注册到GAC并生成类型库 供非托管程序调用:
托管程序集(DotNet.dll)成功生成后,在.NET SDK命令行下注册得到 DotNet.tlb文件:
regasm DotNet.dll /tlb DotNet.tlb
//从GAC中注销( 注销该COM接口 ) regasm /unregister DotNet.dll
(4) 创建非托管C++项目(例子是 Win32 控制台程序 VC++ 2003)
添加刚才生成类型库文件DotNet.tlb的调用到头文件 refer.h (DotNet.tlb要复制到项目根目录下)
////////////////////////////////////////////////// ////////////////////////////
// .NET Specific Header which is included in the C Project
////////////////////////////////////////////////// ////////////////////////////
#pragma warning (disable: 4278)
#include
#import raw_interfaces_only
// Ignoring the server namespace and using named guids:
#if defined (USINGPROJECTSYSTEM)
#import "..\Library\DotNet.tlb" no_namespace named_guids
#else // Compiling from the command line, all files in the same directory
#import "DotNet.tlb" no_namespace named_guids
#endif
using namespace std;
////////////////////////////////////////////////// ////////////////////////////
// End .NET Specific Header, #include this header to the C Main
////////////////////////////////////////////////// ////////////////////////////
编辑cpp主程序文件如下:
#include "refer.h"
//来自托管程序集DotNet.dll里 MyMethods 类的GUID值
const GUID CLSID_LibraryImplementation =
{ 0xde21c7d0, 0xcc57, 0x4ed6, 0xab, 0x55, 0x25, 0xb4, 0xff, 0x8e, 0x33, 0xf2 };
//来自托管程序集DotNet.dll里 IMyInterface 接口类的GUID值
const GUID IID_IManagedInterface =
{ 0xed08e85, 0xa627, 0x4894, 0x91, 0x9c, 0xa4, 0x4, 0xe3, 0x42, 0xf, 0x98 };
//COM调用实现过程
void DoComMethod()
{
coutSay(_str);
CoUninitialize();
test->Release();
cout方法! 如果之前未注册到GAC,会引发COM调用异常!
(5) 客户机布署
将托管和非托管的 exe 或 dll 拷贝到运行目录,注册托管程序集 DotNet.dll 到GAC生成COM接口
在安装了.Net Framework 1.1 的客户机上,进入系统目录里的 .net sdk 相应目录(命令行下),如: C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322
运行命令 regasm DotNet.dll /tlb:DotNet.tlb 注册到GAC生成COM接口,附带生成的 DotNet.tlb 文件可以不用它 (注意:DotNet.dll必须指定路径,上面使用的是默认当前目录下 可在命令行下用 set path="DotNet.dll所在的目录"或 指定 绝对路径),可查看帮助 regasm /?
同理: 在完成上面的步骤之后可选择使用 gacutil /I DotNet.dll 将 DotNet.dll 放到GAC(全局程序集缓存)中,调用 DotNet.dll 就不需要在程序运行目录中查找 该托管dll了:
因为托管dll的调用首先会使用.NET内置的查找算法自动查找GAC,如果里面没有的话,会查找程序配置文件(*.config)里特定参数的指定路径,如果还没有的话,就默认查找当前程序运行目录里的相应dll,再加上该dll已经指定了具体的版本号,相应的接口访问类指定了Guid唯一值,从而使.NET托管下的程序集调用更高效,解决了以前的Dll Hell
发表评论
-
csc.exe命令
2012-01-20 01:10 714csc.exe命令 2010年11月11 ... -
Eclipse插件之Java代码分析工具: FindBugs
2012-01-20 01:09 823Eclipse插件之Java代码分析工具: FindBugs ... -
【开源工程】MediaInfo
2012-01-20 01:09 793【开源工程】MediaInfo 2010年10月28日 ... -
RSA8.0.1安装时可选功能部件描述
2012-01-20 01:09 788RSA8.0.1安装时可选功能部件描述 2011年03月24 ... -
从ADS到RealView MDK
2012-01-19 08:59 731从ADS到RealView MDK 2010年1 ... -
嵌入式Linux的移植的理论问题
2012-01-19 08:59 612嵌入式Linux的移植的理 ... -
记录没见过的词条
2012-01-19 08:59 503记录没见过的词条 2011 ... -
事件管理器――PWM
2012-01-19 08:59 713事件管理器――PWM 2011 ... -
开源工具
2012-01-19 08:59 709开源工具 2011年03月22日 软件集成开发环境(代码 ... -
jianda
2012-01-17 01:29 936jianda 2011年01月15日 ... -
教你入侵16
2012-01-17 01:29 496教你入侵16 2010年07月21 ... -
C语言内存管理(二)
2012-01-17 01:29 819C语言内存管理(二) 2011 ... -
C# 路径,文件,目录,IO常见问题汇总 - wxbjs - 博客园
2012-01-17 01:29 608C# 路径,文件,目录,IO常 ... -
DHT
2012-01-17 01:29 697DHT 2011年04月29日 DHT简介 DHT ... -
在VB中调用CHM 帮助的几种方法
2012-01-15 20:10 532在VB中调用CHM 帮助的几 ... -
学编程的同学看看
2012-01-15 20:10 609学编程的同学看看 2009年11月21日 ... -
三种语言的下载者源代码:C Delphi Vb
2012-01-15 20:10 568三种语言的下载者源代码:C Delphi Vb 2010年0 ... -
发几个vb整人小程序代码.第一次发帖.希望大家多多支持
2012-01-15 20:09 565发几个vb整人小程序代 ... -
VB制作快捷打开电脑里的应用软件比如:我的电脑 网上邻居 等....
2012-01-15 20:09 564VB制作快捷打开电脑里的应用软件比如:我的电脑 网上邻居 等. ... -
Openbravo开发-开发篇 为字段填加约束
2012-01-11 12:19 647Openbravo开发-开发篇 为字段填加约束 2011年0 ...
相关推荐
RunDllMShim 桥接DLL,使从非托管DLL调用程序rundll32.exe调用托管程序集/类型/方法更容易)RunDll流水线Rundll32.exe => Unamanaged Shim => Managed Assembly -> (class,method) 用法rundll32.exe,rdl// this shim...
第一部分 Visual C++ 2010开发与新特性 第1章 Visual C++ 2010开发环境简介 1 1.1 Visual C++ 2010简介 1 1.2 Visual C++ 2010下载安装指南 1 1.3 Visual C++ 2010主要特点与新特性 3 1.4 Visual C++ 2010开发环境...
Fancy.CoreClrHost 使用用户定义的程序集启动.NET Core Crl的主机应用程序。 ##什么是Fancy.CoreClrHost Fancy.CoreClrHost使您可以使用.NET Core Clr运行时启动.NET代码(IL)程序集。 您要运行的程序集可能不依赖...
)专为.NET设计的一门语言,号称“C/C++家族中第一种面向组件的语言”。很多人觉得它应该像C或者C++,但事实上它更像是java的一个clone,所以作为入门,读一下清华大学出版社出版的《Java 语言与面向对象程序设计》...
反射:程序集包含模块,而模块包含类型,类型又包含成员。反射则提供了封装程序集、模块和类型的对象。您可以使用反射动态地创建类型的实例,将类型绑定到现有对象,或从现有对象中获取类型。然后,可以调用类型的...
用您喜欢的.NET语言为Chromium编写PPAPI扩展。 该项目处于非常早期的原型阶段。 它可以使用.NET Framework或CoreCLR调用托管程序集。 但这就是它目前所能做的-调用它。 它还没有以任何方式与电子相互作用。
17.8 从Python可调用的C函数中返回None 611 17.9 用gdb调试动态载入的C扩展 613 17.10 调试内存问题 614 第18章 算法 616 引言 616 18.1 消除序列中的重复 619 18.2 在保留序列顺序的前提下消除其中的重复 ...