2024年1月1日发(作者:)

VisualC、delphi或者vb等编程语言来编写的DLL文件,在编译完成以后,产生DLL文件[wen jian]已经是一个可以直接供计算机使用的二进制文件,而Visual c#生成的DLL不是独立运行的程序,是某个程序的一个部分,只能由所属的程序调用,用户不能也不需要打开它,Visual C#编译器生成的托管代码虽然也是二进制文件,但不是可以直接供计算机使用的原始代码,实际上是一种中间语言(IL)代码,需要经过"下一代窗口服务"( Next Generation Windows Services,简写为NGWS ) runtime的即时编译器(即JIT)进行编译。用Visual C#生成的DLL文件已经和以前的DLL文件有了本质上的区别。用Visual C#生成的DLL文件在程序设计中更多的表现为一种类(Class)或者类库(Class Library)。

如果想在vc++的非托管代码中调用已经用VC#生成的托管的DLL,从两个方向进行调整可以产生两种办法:(visual studio 2008)(下面方法都是对于同一平台下,即C#跟VC++都是在windows平台下)

一、对VC++的环境中进行修改使其支持托管代码:

vc++调用端增加公共语言运行时【clr】的支持以执行C#的程序:

【解决方案】 ->【 Properties】(右键)-> 【Configuration Properties】(展开左树) -> 【General】(打开子节点) -> 【Common Language Runtime support】(选中选项) ->【Common Language Runtime

support(/clr)】(选中)

OK,现在就可以引入托管的动态连接库来用了,不过在调用时还是得注意语法(new->gcnew,....),例如下:

#include "stdafx.h"

#using ""

using namespace SmartDeviceDLL;

int _tmain(int argc, _TCHAR* argv[])

{

printf("11n");

SmartDeviceDLL::ICalculator ^pICalc= gcnew SmartDeviceDLL::Class1();

long lResult =0;

lResult=pICalc->Add(5,10);

wprintf(L"the result is %dn",lResult);

printf("222222222222222222n");

char c;

scanf("%c",&c);

return 0;

}

二、C#生成DLL端编译成COM接口,供VC++以托管格式调用(命令的运行都是在visual studio

command prompt (命令窗口)中)

1.新建一个C#的动态连接库(在模板 ,下单击类库):

using System;

using ;

using c;

using ;

namespace SmartDeviceDLL

{

public interface ICalculator

{

int Add(int Number1, int Number2);

}

public class Class1: ICalculator

{

public int Add(int Number1, int Number2)

{

return Number1 * Number2;

}

public static int TestMethod(String s)

{

ine("Managed assembly: [0]", s);

return ;

}

}

}

2.为程序集创建一个强命名的类库,并在文件中用AssemblyKeyFile属性指向它:

1)、使用强命名工具(Strong Name Utility)产生密钥对:

sn -k

2)、在文件中用AssemblyKeyFile属性指向它:

即在项目的文件中将[assembly: ComVisible(false)]用以下内容替换:

[assembly: ComVisible(true)]

[assembly: AssemblyDelaySign(false)]

[assembly: AssemblyKeyFile("")] //指向刚生成的文件(可用无汉字的绝对路径)

3)、重新编译,产生的程序集就是经过签名后的程序集了

3.把生成的库文件加入全局程序集缓存(Global Assembly Cache, .NET [Compact]Framework支持一个工具,通常位于:CWndowsAssembly下)以便可以从任何 COM 客户端激活它,可以使用工具,指定/i命令开关将一个程序集安装到GAC中,同样可以使用/u命令开关将一个程序集从GAC中卸载。注意:安装的程序集必须是强命名程序集:

GACUTIL /i //可用的绝对路径,Wince平台直接在命令窗口中用CGACUTIL(Compact)

4.用下面的命令为COM注册刚才的程序集,生成COM库文件(程序集注册工具读取程序集中的元数据,并将所需的项添加到注册表中,注册表允许 COM 客户程序以透明方式创建 .NET Framework 类。类一经注册,任何 COM 客户程序都可以使用它,就好像该类是一个 COM 类。类仅在安装程序集时注册一次。程序集中的类实例直到被实际注册时,才能从 COM 中创建)

//下面命令注册 中包含的所有公共类,并生成和注册类型库

,该类型库包含 中定义的所有公共类型的定义

REGASM /tlb:

//或者可以选中:【解决方案】 ->【Properties】(右键)-> 【Build】 ->【Register for COM interop】(Wince平台的DLL此选项不可选)

5.创建非托管的VC++调用程序(此处用Win32 Console Project为例):

#include "stdafx.h"

#import "" named_guids raw_interfaces_only

using namespace SmartDeviceDLL;

int _tmain(int argc, _TCHAR* argv[])

{

printf("11n");

//初始化COM以及产生智能指针

HRESULT hr=CoInitializeEx(NULL,COINIT_MULTITHREADED);

if(hr!=S_OK)

printf("hr failedn");

else

printf("hr okn");

printf("222222222222222222n");

SmartDeviceDLL::ICalculatorPtr pICalc;

printf("2.1n");

HRESULT hRes=Instance(__uuidof(Class1),NULL,CLSCTX_ALL);

//HRESULT hRes=Instance(SmartDeviceDLL::CLSID_Class1);

printf("2.2n");

if(hRes==S_OK)

{

printf("hRes okn");

long lResult =0;

pICalc->Add(5,10, &lResult);

wprintf(L"the result is %dn",lResult);

}

else

printf("hRes failuren");

printf("333333333333n");

CoUninitialize();

printf("4444444444444444444n");

char c;

scanf("%c",&c);

return 0;

}

補充:

使用第1種方法時,字符串的處理:

1)System::String -> char *:

char *ILStringToMultiBytes(System::String ^ilstring, char *multiBytes)

{

const int LINE_SIZE = 256;

wchar_t wideBytes[LINE_SIZE];

for (int i = 0; i < ilstring->Length; ++i)

{

wideBytes[i] = ilstring[i];

//cout << nameW << endl;

}

WideCharToMultiByte(CP_ACP, 0, wideBytes, ilstring->Length + 1, multiBytes, ilstring->Length,

NULL, NULL);

multiBytes[ilstring->Length + 1] = '0';

return multiBytes;

}

2) char* -> System::String:

System::String ^string = gcnew System::String(multiBytes);