.net中调用VC++编写的DLL文件

由于VC 6.0编写的DLL没有自描述,所以无法像C#.net编写的DLL一样直接引用调用,一般可以采用两种方法调用。

一、注册成COM组件:用命令regsvr32 DllFilePath进行注册,然后引用到项目。

二、一些非COM组件的DLL文件可以在程序中用如下格式,将其中需要调用的函数一个一个的引用声明出来。一些数据格式的对应见下表。

调用DLL中的非托管函数一般方法,基本格式:[DLLImport(“DLL文件”)]

                    public static extern void function_name(datetype args,...);

                    修饰符 extern 返回变量类型 方法名称  (参数列表)

 

其中:

DLL文件:包含定义外部方法的库文件。

修饰符:  访问修饰符,除了abstract以外在声明方法时可以使用的修饰符。

返回变量类型:在DLL文件中你需调用方法的返回变量类型。

方法名称:在DLL文件中你需调用方法的名称。

参数列表:在DLL文件中你需调用方法的列表。

 

注意:需要在程序声明中使用System.Runtime.InteropServices命名空间。

      DllImport只能放置在方法声明上。

DLL文件必须位于程序当前目录或系统定义的查询路径中(即:系统环境变量中Path所设置的路径)。

返回变量类型、方法名称、参数列表一定要与DLL文件中的定义相一致,若要使用其它函数名,可以使用EntryPoint属性设置,如:

[DllImport("user32.dll", EntryPoint="MessageBoxA")]

static extern int MsgBox(int hWnd, string msg, string caption, int type);

 

DllImport 属性具有下列行为:

它只能放置在方法声明上。

它具有单个定位参数:指定包含被导入方法的 dll 名称的 dllName 参数。

它具有五个命名参数:

 CallingConvention 参数指示入口点的调用约定。如果未指定 CallingConvention,则使用默认值CallingConvention.Winapi。

CharSet 参数指示用在入口点中的字符集。如果未指定 CharSet,则使用默认值 CharSet.Auto。

EntryPoint 参数给出 dll 中入口点的名称。如果未指定 EntryPoint,则使用方法本身的名称。

ExactSpelling 参数指示 EntryPoint 是否必须与指示的入口点的拼写完全匹配。如果未指定ExactSpelling,则使用默认值 false。

PreserveSig 参数指示方法的签名应当被保留还是被转换。当签名被转换时,它被转换为一个具有HRESULT 返回值和该返回值的一个名为 retval 的附加输出参数的签名。如果未指定 PreserveSig,则使用默认值 true。 SetLastError 参数指示方法是否保留 Win32“上一错误”。如果未指定 SetLastError,则使用默认值false。 它是一次性属性类。

此外,用 DllImport 属性修饰的方法必须具有 extern 修饰符。

是的,上面就是MSDN原文内容.好了继续我们的例子,好了,先把我们上面的C代码编译成DLL叫什么呢?那就叫MYDLLTest好了.

[DllImport("MYDLLTest.dll",EntryPoint="average",ExactSpelling=false,CallingConvention=CallingConvention.Cdecl)]

static extern int average(int av[]);

 

 

 

 

C++数据类型和C#的部分对应关系

C++ I/O C# 备注
char chr[255] O StringBuilder StringBuilder在使用时,必须指定大小:

 

StringBuilder strPara = new StringBuilder(255);

KCA_DIR I int  
LPCSTR I string  
int I int  
LPSTR O StringBuilder  
int* O out int  
DWORD I int  
DWORD* O out int  
BOOL I bool  
long* O out long  
HWND I IntPrt 可以用Int32代替,不过建议使用IntPrt

 

 例子:在一个C#程序中调用Win32API mciSendString函数控制光盘驱动器,这个函数的函数原型是: 

MCIERROR mciSendString( 
LPCTSTR lpszCommand, 
LPTSTR lpszReturnString, 
UINT cchReturn, 
HANDLE hwndCallback 
); 

首先在C#中声明这个函数: 
[DllImport("winmm.dll")] 
private static extern long mciSendString(string a,string b,uint c,IntPtr d); 

然后用这样的方法调用: 
mciSendString("set cdaudio door open", null, 0, this.Handle); 

您也可以使用IntPtr.Zero将句柄设置为0; 
或者使用类型强制转换: 
mciSendString("set cdaudio door open", null, 0, (IntPtr)0 ); 

或者,使用IntPtr构造函数: 
IntPtr a = new IntPtr(2121); 


这里有两点比较重要: 
一是在C#中声明Win32API时,一定要按照WinAPI的原型来声明,不要改变它的数据类型; 
二是尽量不要过多使用类型强制转换或构造函数的方式初始化一个IntPtr类型的变量,这样会使程序变得难于理解并容易出错。

 

 
 
 
 
 
posted @ 2013-01-03 15:39  奎宇工作室  阅读(336)  评论(0编辑  收藏  举报