C#调用C++编写的COM DLL

时间:2022-08-31 09:15:26

在C#调用C++编写的COM DLL封装库时会出现两个问题:

1.  数据类型转换问题
2.  指针或地址参数传送问题
 
    首先是数据类型转换问题。因为C#是.NET语言,利用的是.NET的基本数据类型,所以实际上是将C++的数据类型与.NET的基本数据类型进行对应。
 
    例如C++的原有函数是:
 
int __stdcall FunctionName(unsigned char param1, unsigned short param2)
 
    其中的参数数据类型在C#中,必须转为对应的数据类型。如:
 
[DllImport(“ COM DLL path/file ”)]
extern static int FunctionName(byte param1, ushort param2)
 
    因为调用的是__stdcall函数,所以使用了P/Invoke的调用方法。其中的方法FunctionName必须声明为静态外部函数,即加上 extern static声明头。我们可以看到,在调用的过程中,unsigned char变为了byte,unsigned short变为了ushort。变换后,参数的数据类型不变,只是声明方式必须改为.NET语言的规范。
 
    我们可以通过下表来进行这种转换:
 

 

Win32 Types
CLR Type
char, INT8, SBYTE, CHAR 
System.SByte
short, short int, INT16, SHORT
System.Int16
int, long, long int, INT32, LONG32, BOOL , INT
System.Int32
__int64, INT64, LONGLONG
System.Int64
unsigned char, UINT8, UCHAR , BYTE
System.Byte
unsigned short, UINT16, USHORT, WORD, ATOM, WCHAR , __wchar_t
System.UInt16
unsigned, unsigned int, UINT32, ULONG32, DWORD32, ULONG, DWORD, UINT
System.UInt32
unsigned __int64, UINT64, DWORDLONG, ULONGLONG
System.UInt64
float, FLOAT
System.Single
double, long double, DOUBLE
System.Double
 
    之后再将CLR的数据类型表示方式转换为C#的表示方式。这样一来,函数的参数类型问题就可以解决了。
 
    现在,我们再来考虑下一个问题,如果要调用的函数参数是指针或是地址变量,怎么办?
 
    对于这种情况可以使用C#提供的非安全代码来进行解决,但是,毕竟是非托管代码,垃圾资源处理不好的话对应用程序是很不利的。所以还是使用C#提供的 ref以及out修饰字比较好。
 
    同上面一样,我们也举一个例子:
 
int __stdcall FunctionName(unsigned char &param1, unsigned char *param2)
 
    在C#中对其进行调用的方法是:
 
[DllImport(“ COM DLL path/file ”)]
extern static int FunctionName(ref byte param1, ref byte param2)
 
    看到这,可能有人会问,&是取地址,*是传送指针,为何都只用ref就可以了呢?一种可能的解释是ref是一个具有重载特性的修饰符,会自动识别 是取地址还是传送指针。
 
    在实际的情况中,我们利用参数传递地址更多还是用在传送数组首地址上。
如:byte[] param1 = new param1(6);
 
    在这里我们声明了一个数组,现在要将其的首地址传送过去,只要将param1数组的第一个元素用ref修饰。具体如下:
 
[DllImport(“ COM DLL path/file ”)]
extern static int FunctionName(ref byte param1[1], ref byte param2)

 

C#调用DLL函数方法

http://www.csharpwin.net/ddwstp/net/csharp/5964dr984.shtml

http://www.csharpwin.net/ddwstp/net/csharp/5970dr7788.shtml

 

首先,理解托管代码与非托管代码的区别:

    1.托管代码所申请的资源统一由.Net Framework管理,你不用操心,非托管代码所申请的内存等资源则需要你手动去释放  

    2.非托管程序运行会很快,是二进制的,托管程序好写,但是速度就差的很多,资源会用的很多

    3.“程序"一般都是在对操作系统进行直接或者间接的操作  

    "托管程序"是需要通过访问公共语言运行时(cls)才能访问操作系统的程序,而“非托管程序”不用通过访问公共语言运行时(cls)可以直接访问操作系 统的程序  

    4.vb.net,C#等写的程序是托管程序,VC++可以写托管程序,如果用到了内存管理,则只能编译为非托管程序

    VC++写托管的是要用.net的库,因为我们没有用.net,所以只用了非托管方式。

    (一) C#调用DLL中的非托管函数一般方法

    首先,应该在C#语言源程序中声明外部方法,其基本形式是:

    [DLLImport(“DLL文件”)]

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

    其中:

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

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

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

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

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

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

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

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

    返回变量类型、方法名称、参数列表一定要与DLL文件中的定义相一致。

    其它可选的 DllImportAttribute 属性:

    CharSet 指示用在入口点中的字符集,如:CharSet=CharSet.Ansi;

    SetLastError 指示方法是否保留 Win32"上一错误",如:SetLastError=true;

    ExactSpelling 指示 EntryPoint 是否必须与指示的入口点的拼写完全匹配,如:ExactSpelling=false;

    PreserveSig指示方法的签名应当被保留还是被转换, 如:PreserveSig=true;

    CallingConvention指示入口点的调用约定, 如:CallingConvention=CallingConvention.Winapi;

    此外,关于“数据封送处理”及“封送数字和逻辑标量”请参阅其它一些文章。

    举例:

    New file,选择visual C# Class。在文件中,创建一个public的类。把待测试的函数在这个类中作声明。

  1. p​u​b​l​i​c c​l​a​s​s ​C​l​a​s​s​N​a​m​e​ ​ ​ ​ ​  
  2. {​ ​ ​ ​ ​ ​ ​ ​  
  3.  ​ ​ ​[​D​l​l​I​m​p​o​r​t​("​x​x​x​.​d​l​l​",​ ​E​n​t​r​y​P​o​i​n​t​ ​=​ "​x​x​")​]​ ​ 
  4.  ​ ​ ​ ​ ​ ​ ​ p​u​b​l​i​c s​t​a​t​i​c e​x​t​e​r​n i​n​t ​S​t​a​r​t​V​i​d​e​o​(
  5. i​n​t ​n​D​e​v​N​u​m​,​ i​n​t ​S​w​i​t​c​h​i​n​g​C​h​a​n​s​,​ ​I​n​t​P​t​r​ ​M​a​i​n​,​ ​I​n​t​P​t​r​ ​h​w​n​d​P​r​e​v​i​e​w​)​;​ ​  
  6. }​ ​  

    Xxx为待测试的dll名称,xx为dll中提供的方法函数。若要使用其它函数名,可以使用EntryPoint属性设置。

    如何用DllImport调用DLL中的非托管函数,但是这个是全局的函数,假若DLL中的非托管函数有一个静态变量S,每次调用这个函数的时候,静态变 量S就自动加1。结果,当需要重新计数时,就不能得出想要的结果。所以,要注意啊,用DllImport调用DLL中的非托管函数是全局的、静态的函数。

    以上介绍的就是C#调用DLL函数方法(上),剩下的内容将在C#调用DLL函数方法(下)中继续给大家讲解。

  因为C#中使用DllImport是不能像动态load/unload assembly那样,所以只能借助API函数了。在kernel32.dll中,与动态库调用有关的函数包括[3]:

    ①LoadLibrary(或MFC 的AfxLoadLibrary),装载动态库。

    ②GetProcAddress,获取要引入的函数,将符号名或标识号转换为DLL内部地址。

    ③FreeLibrary(或MFC的AfxFreeLibrary),释放动态链接库。

    它们的原型分别是:

    HMODULE LoadLibrary(LPCTSTR lpFileName);

    FARPROC GetProcAddress(HMODULE hModule, LPCWSTR lpProcName);

    BOOL FreeLibrary(HMODULE hModule);

    现在,我们可以用IntPtr hModule=LoadLibrary(“Count.dll”);来获得Dll的句柄,用IntPtr farProc=GetProcAddress(hModule,”_count@4”);来获得函数的入口地址。

    但是,知道函数的入口地址后,怎样调用这个函数呢?因为在C#中是没有函数指针的,没有像C++那样的函数指针调用方式来调用函数,所以我们得借助其它方 法。经过研究,发现我们可以通过结合使用System.Reflection.Emit及System.Reflection.Assembly里的类和 函数达到我们的目的。为了以后使用方便及实现代码的复用,我们可以编写一个类。

    1) dld类的编写:

    1.打开项目“Test”,打开类视图,右击“Tzb”,选择“添加”-->“类”,类名设置为“dld”,即dynamic loading dll 的每个单词的开头字母。

    2.添加所需的命名空间及声明参数传递方式枚举:

  1. u​s​i​n​g ​S​y​s​t​e​m​.​R​u​n​t​i​m​e​.​I​n​t​e​r​o​p​S​e​r​v​i​c​e​s​;​ /​/​ ​用​D​l​l​I​m​p​o​r​t​ ​需​用​此​命​名​空​间  
  2. u​s​i​n​g ​S​y​s​t​e​m​.​R​e​f​l​e​c​t​i​o​n​;​ /​/​ ​使​用​A​s​s​e​m​b​l​y​ ​类​需​用​此​命​名​空​间   
  3. u​s​i​n​g ​S​y​s​t​e​m​.​R​e​f​l​e​c​t​i​o​n​.​E​m​i​t​;​ /​/​ ​使​用​I​L​G​e​n​e​r​a​t​o​r​ ​需​用​此​命​名​空​间  

    3. 在namespace test中,“public class dld”的上面,添加如下代码声明参数传递方式枚举:

 

  1. /​/​/​ ​<​ ​s​u​m​m​a​r​y​>​    
  2.  ​ ​ ​ /​/​/​ ​参​数​传​递​方​式​枚​举​,​B​y​V​a​l​u​e​ ​表​示​值​传​递​,​B​y​R​e​f​ ​表​示​址​传​递   
  3.  ​ ​ ​ /​/​/​ ​<​ ​/​s​u​m​m​a​r​y​>​    
  4.  ​ ​ ​ p​u​b​l​i​c e​n​u​m ​M​o​d​e​P​a​s​s​ ​  
  5.  ​ ​ ​ ​{​ ​ 
  6.  ​ ​ ​ ​ ​ ​ ​ ​B​y​V​a​l​u​e​ ​=​ ​0​x​0​0​0​1​,​ ​  
  7.  ​ ​ ​ ​ ​ ​ ​ ​B​y​R​e​f​ ​=​ ​0​x​0​0​0​2​ ​  
  8. }​ ​  

    4、在public class DLD中,添加如下代码:

 

  1. p​u​b​l​i​c c​l​a​s​s ​D​L​D​ ​ 
  2.  ​ ​ ​ ​{​ ​ 
  3.  ​ ​ ​ ​ ​ ​ ​ ​[​D​l​l​I​m​p​o​r​t​("​k​e​r​n​e​l​3​2​.​d​l​l​")​]​ ​ 
  4.  ​ ​ ​ ​ ​ ​ ​ p​u​b​l​i​c s​t​a​t​i​c e​x​t​e​r​n ​I​n​t​P​t​r​ ​L​o​a​d​L​i​b​r​a​r​y​(s​t​r​i​n​g ​l​p​F​i​l​e​N​a​m​e​)​;​ ​ 
  5.  
  6.  ​ ​ ​ ​ ​ ​ ​ ​[​D​l​l​I​m​p​o​r​t​("​k​e​r​n​e​l​3​2​.​d​l​l​")​]​ ​ 
  7.  ​ ​ ​ ​ ​ ​ ​ p​u​b​l​i​c s​t​a​t​i​c e​x​t​e​r​n ​I​n​t​P​t​r​ ​G​e​t​P​r​o​c​A​d​d​r​e​s​s​(
  8. I​n​t​P​t​r​ ​h​M​o​d​u​l​e​,​ s​t​r​i​n​g ​l​p​P​r​o​c​e​N​a​m​e​)​;​ ​ 
  9.  
  10.  ​ ​ 
  11.  
  12.  ​ ​ ​ ​ ​ ​ ​ ​[​D​l​l​I​m​p​o​r​t​("​k​e​r​n​e​l​3​2​",​ ​E​n​t​r​y​P​o​i​n​t​ ​=​ "​F​r​e​e​L​i​b​r​a​r​y​",​ ​S​e​t​L​a​s​t​E​r​r​o​r​ ​=​ t​r​u​e)​]​ ​ 
  13.  ​ ​ ​ ​ ​ ​ ​ ​ ​ p​u​b​l​i​c s​t​a​t​i​c e​x​t​e​r​n b​o​o​l ​F​r​e​e​L​i​b​r​a​r​y​(​I​n​t​P​t​r​ ​h​M​o​d​u​l​e​)​;​ ​ 
  14.  
  15.  ​ ​ 
  16.  
  17.  ​ ​ ​ ​ ​ ​ ​ /​/​/​ ​<​ ​s​u​m​m​a​r​y​>​    
  18.  ​ ​ ​ ​ ​ ​ ​ /​/​/​ ​L​o​a​d​l​i​b​r​a​r​y​ ​返​回​的​函​数​库​模​块​的​句​柄​    
  19.  ​ ​ ​ ​ ​ ​ ​ /​/​/​ ​<​ ​/​s​u​m​m​a​r​y​>​    
  20.  ​ ​ ​ ​ ​ ​ ​ p​r​i​v​a​t​e ​I​n​t​P​t​r​ ​h​M​o​d​u​l​e​ ​=​ ​I​n​t​P​t​r​.​Z​e​r​o​;​ ​ 
  21.   
  22.  ​ ​ ​ ​ ​ ​ ​ /​/​/​ ​<​ ​s​u​m​m​a​r​y​>​    
  23.  ​ ​ ​ ​ ​ ​ ​ /​/​/​ ​G​e​t​P​r​o​c​A​d​d​r​e​s​s​ ​返​回​的​函​数​指​针​    
  24.  ​ ​ ​ ​ ​ ​ ​ /​/​/​ ​<​ ​/​s​u​m​m​a​r​y​>​   
  25.  ​ ​ ​ ​ ​ ​ ​ p​r​i​v​a​t​e ​I​n​t​P​t​r​ ​f​a​r​P​r​o​c​ ​=​ ​I​n​t​P​t​r​.​Z​e​r​o​;​ ​ 
  26.  
  27.  ​ ​ ​ ​ ​ ​ ​ /​/​/​ ​<​ ​s​u​m​m​a​r​y​>​    
  28.  ​ ​ ​ ​ ​ ​ ​ /​/​/​ ​装​载​ ​D​l​l​    
  29.  ​ ​ ​ ​ ​ ​ ​ /​/​/​ ​<​ ​/​s​u​m​m​a​r​y​>​    
  30.  ​ ​ ​ ​ ​ ​ ​ /​/​/​ ​<​ ​p​a​r​a​m​ ​n​a​m​e​=​"​l​p​F​i​l​e​N​a​m​e​"​>​D​L​L​ ​文​件​名​ ​<​ ​/​p​a​r​a​m​>​   
  31.  ​ ​ ​ ​ ​ ​ ​ p​u​b​l​i​c v​o​i​d ​L​o​a​d​D​l​l​(s​t​r​i​n​g ​l​p​F​i​l​e​N​a​m​e​)​ ​ 
  32.  ​ ​ ​ ​ ​ ​ ​ ​{​ ​ 
  33.   
  34.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​h​M​o​d​u​l​e​ ​=​ ​L​o​a​d​L​i​b​r​a​r​y​(​l​p​F​i​l​e​N​a​m​e​)​;​ ​ 
  35.  
  36.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ i​f ​(​h​M​o​d​u​l​e​ ​=​=​ ​I​n​t​P​t​r​.​Z​e​r​o​)​ ​ 
  37.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ t​h​r​o​w ​(n​e​w ​E​x​c​e​p​t​i​o​n​("​ ​没​有​找​到​ ​:​" ​+​ ​l​p​F​i​l​e​N​a​m​e​ ​+​ "​.​")​)​;​ ​ 
  38.  ​ ​ ​ ​ ​ ​ ​ ​}​ ​ 
  39.  
  40.  
  41.  ​ ​ ​ ​ ​ ​ ​ /​/​/​ ​<​ ​s​u​m​m​a​r​y​>​   
  42.  ​ ​ ​ ​ ​ ​ ​ /​/​/​ ​获​得​函​数​指​针​    
  43.  ​ ​ ​ ​ ​ ​ ​ /​/​/​ ​<​ ​/​s​u​m​m​a​r​y​>​   
  44.  ​ ​ ​ ​ ​ ​ ​ /​/​/​ ​<​ ​p​a​r​a​m​ ​n​a​m​e​=​"​l​p​P​r​o​c​N​a​m​e​"​>​ ​调​用​函​数​的​名​称​ ​<​ ​/​p​a​r​a​m​>​    
  45.  ​ ​ ​ ​ ​ ​ ​ p​u​b​l​i​c v​o​i​d ​L​o​a​d​F​u​n​(s​t​r​i​n​g ​l​p​P​r​o​c​N​a​m​e​)​ ​  
  46.  ​ ​ ​ ​ ​ ​ ​ ​{​ /​/​ ​若​函​数​库​模​块​的​句​柄​为​空​,​则​抛​出​异​常​   
  47.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ i​f ​(​h​M​o​d​u​l​e​ ​=​=​ ​I​n​t​P​t​r​.​Z​e​r​o​)​ ​  
  48.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ t​h​r​o​w ​(n​e​w ​E​x​c​e​p​t​i​o​n​(
  49. "​ ​函​数​库​模​块​的​句​柄​为​空​ ​,​ ​请​确​保​已​进​行​ ​L​o​a​d​D​l​l​ ​操​作​ ​!​")​)​;​ ​  
  50.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ /​/​ ​取​得​函​数​指​针​   
  51.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​f​a​r​P​r​o​c​ ​=​ ​G​e​t​P​r​o​c​A​d​d​r​e​s​s​(​h​M​o​d​u​l​e​,​ ​l​p​P​r​o​c​N​a​m​e​)​;​ ​ 
  52.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ /​/​ ​若​函​数​指​针​,​则​抛​出​异​常​    
  53.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ i​f ​(​f​a​r​P​r​o​c​ ​=​=​ ​I​n​t​P​t​r​.​Z​e​r​o​)​ ​  
  54.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ t​h​r​o​w ​(n​e​w ​E​x​c​e​p​t​i​o​n​(
  55. "​ ​没​有​找​到​ ​:​" ​+​ ​l​p​P​r​o​c​N​a​m​e​ ​+​ "​ ​这​个​函​数​的​入​口​点​ ​")​)​;​ ​  
  56.  ​ ​ ​ ​ ​ ​ ​ ​}​ ​ 
  57.  
  58.  ​ ​ 
  59.  
  60.  ​ ​ ​ ​ ​ ​ ​ /​/​/​ ​<​ ​s​u​m​m​a​r​y​>​    
  61.  ​ ​ ​ ​ ​ ​ ​ /​/​/​ ​卸​载​ ​D​l​l​    
  62.  ​ ​ ​ ​ ​ ​ ​ /​/​/​ ​<​ ​/​s​u​m​m​a​r​y​>​    
  63.  ​ ​ ​ ​ ​ ​ ​ p​u​b​l​i​c v​o​i​d ​U​n​L​o​a​d​D​l​l​(​)​ ​  
  64.  ​ ​ ​ ​ ​ ​ ​ ​{​ ​ 
  65.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​F​r​e​e​L​i​b​r​a​r​y​(​h​M​o​d​u​l​e​)​;​ ​  
  66.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​h​M​o​d​u​l​e​ ​=​ ​I​n​t​P​t​r​.​Z​e​r​o​;​ ​  
  67.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​f​a​r​P​r​o​c​ ​=​ ​I​n​t​P​t​r​.​Z​e​r​o​;​ ​ 
  68.  ​ ​ ​ ​ ​ ​ ​ ​}​ ​ 
  69.  
  70.  ​ ​ 
  71.  ​ ​ ​ ​ ​ ​ ​ /​/​/​ ​<​ ​s​u​m​m​a​r​y​>​    
  72.  ​ ​ ​ ​ ​ ​ ​ /​/​/​ ​调​用​所​设​定​的​函​数​   
  73.  ​ ​ ​ ​ ​ ​ ​ /​/​/​ ​<​ ​/​s​u​m​m​a​r​y​>​   
  74.  ​ ​ ​ ​ ​ ​ ​ /​/​/​ ​<​ ​p​a​r​a​m​ ​n​a​m​e​=​"​O​b​j​A​r​r​a​y​_​P​a​r​a​m​e​t​e​r​"​>​ ​实​参​ ​<​ ​/​p​a​r​a​m​>​   
  75.  ​ ​ ​ ​ ​ ​ ​ /​/​/​ ​<​ ​p​a​r​a​m​ ​n​a​m​e​=​"​T​y​p​e​A​r​r​a​y​_​P​a​r​a​m​e​t​e​r​T​y​p​e​"​>​ ​实​参​类​型​ ​<​ ​/​p​a​r​a​m​>​   
  76.  ​ ​ ​ ​ ​ ​ ​ /​/​/​ ​<​ ​p​a​r​a​m​ ​n​a​m​e​=​"​M​o​d​e​P​a​s​s​A​r​r​a​y​_​P​a​r​a​m​e​t​e​r​"​>​ ​实​参​传​送​方​式​ ​<​ ​/​p​a​r​a​m​>​   
  77.  ​ ​ ​ ​ ​ ​ ​ /​/​/​ ​<​ ​p​a​r​a​m​ ​n​a​m​e​=​"​T​y​p​e​_​R​e​t​u​r​n​"​>​ ​返​回​类​型​ ​<​ ​/​p​a​r​a​m​>​    
  78.  ​ ​ ​ ​ ​ ​ ​ /​/​/​ ​<​ ​r​e​t​u​r​n​s​>​ ​返​回​所​调​用​函​数​的​ ​o​b​j​e​c​t​<​ ​/​r​e​t​u​r​n​s​>​   
  79.  ​ ​ ​ ​ ​ ​ ​ p​u​b​l​i​c o​b​j​e​c​t ​I​n​v​o​k​e​(
  80. o​b​j​e​c​t[​]​ ​O​b​j​A​r​r​a​y​_​P​a​r​a​m​e​t​e​r​,​ ​T​y​p​e​[​]​ ​T​y​p​e​A​r​r​a​y​_​P​a​r​a​m​e​t​e​r​T​y​p​e​,
  81.  ​M​o​d​e​P​a​s​s​[​]​ ​M​o​d​e​P​a​s​s​A​r​r​a​y​_​P​a​r​a​m​e​t​e​r​,​ ​T​y​p​e​ ​T​y​p​e​_​R​e​t​u​r​n​)​ ​ 
  82.  ​ ​ ​ ​ ​ ​ ​ ​{​ ​ 
  83.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ /​/​ ​下​面​ ​3​ ​个​ ​i​f​ ​是​进​行​安​全​检​查​ ​,​ ​若​不​能​通​过​ ​,​ ​则​抛​出​异​常​   
  84.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ i​f ​(​h​M​o​d​u​l​e​ ​=​=​ ​I​n​t​P​t​r​.​Z​e​r​o​)​ ​ 
  85.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ t​h​r​o​w ​(n​e​w ​E​x​c​e​p​t​i​o​n​(
  86. "​ ​函​数​库​模​块​的​句​柄​为​空​ ​,​ ​请​确​保​已​进​行​ ​L​o​a​d​D​l​l​ ​操​作​ ​!​")​)​;​ ​ 
  87.  
  88.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ i​f ​(​f​a​r​P​r​o​c​ ​=​=​ ​I​n​t​P​t​r​.​Z​e​r​o​)​ ​ 
  89.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ t​h​r​o​w ​(n​e​w ​E​x​c​e​p​t​i​o​n​("​ ​函​数​指​针​为​空​ ​,​ ​请​确​保​已​进​行​ ​L​o​a​d​F​u​n​ ​操​作​ ​!​")​)​;​ ​ 
  90.  ​ ​ ​ ​ ​ ​ i​f ​(​O​b​j​A​r​r​a​y​_​P​a​r​a​m​e​t​e​r​.​L​e​n​g​t​h​ ​!​=​ ​M​o​d​e​P​a​s​s​A​r​r​a​y​_​P​a​r​a​m​e​t​e​r​.​L​e​n​g​t​h​)​ ​ 
  91.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ t​h​r​o​w ​(n​e​w ​E​x​c​e​p​t​i​o​n​("​ ​参​数​个​数​及​其​传​递​方​式​的​个​数​不​匹​配​ ​.​")​)​;​ ​ 
  92.  
  93.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ /​/​ ​下​面​是​创​建​ ​M​y​A​s​s​e​m​b​l​y​N​a​m​e​ ​对​象​并​设​置​其​ ​N​a​m​e​ ​属​性​ 
  94.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​A​s​s​e​m​b​l​y​N​a​m​e​ ​M​y​A​s​s​e​m​b​l​y​N​a​m​e​ ​=​ n​e​w ​A​s​s​e​m​b​l​y​N​a​m​e​(​)​;​ ​ 
  95.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​M​y​A​s​s​e​m​b​l​y​N​a​m​e​.​N​a​m​e​ ​=​ "​I​n​v​o​k​e​F​u​n​";​ ​ 
  96.  
  97.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ /​/​ ​生​成​单​模​块​配​件​   
  98.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​A​s​s​e​m​b​l​y​B​u​i​l​d​e​r​ ​M​y​A​s​s​e​m​b​l​y​B​u​i​l​d​e​r​ ​=​ 
  99. A​p​p​D​o​m​a​i​n​.​C​u​r​r​e​n​t​D​o​m​a​i​n​.​D​e​f​i​n​e​D​y​n​a​m​i​c​A​s​s​e​m​b​l​y​(
  100. M​y​A​s​s​e​m​b​l​y​N​a​m​e​,​ ​A​s​s​e​m​b​l​y​B​u​i​l​d​e​r​A​c​c​e​s​s​.​R​u​n​)​;​ ​ 
  101.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​M​o​d​u​l​e​B​u​i​l​d​e​r​ ​M​y​M​o​d​u​l​e​B​u​i​l​d​e​r​ ​=​ ​M​y​A​s​s​e​m​b​l​y​B​u​i​l​d​e​r​.​D​e​f​i​n​e​D​y​n​a​m​i​c​M​o​d​u​l​e​(
  102. "​I​n​v​o​k​e​D​l​l​")​;​ ​ 
  103.   
  104.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ /​/​ ​定​义​要​调​用​的​方​法​ ​,​ ​方​法​名​为​“​ ​M​y​F​u​n​ ​”​,
  105. /​/返​回​类​型​是​“​ ​T​y​p​e​_​R​e​t​u​r​n​ ​”​参​数​类​型​是​“​ ​T​y​p​e​A​r​r​a​y​_​P​a​r​a​m​e​t​e​r​T​y​p​e​ ​”​   
  106.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​M​e​t​h​o​d​B​u​i​l​d​e​r​ ​M​y​M​e​t​h​o​d​B​u​i​l​d​e​r​ ​=​ ​M​y​M​o​d​u​l​e​B​u​i​l​d​e​r​.​D​e​f​i​n​e​G​l​o​b​a​l​M​e​t​h​o​d​(
  107. "​M​y​F​u​n​",​ ​M​e​t​h​o​d​A​t​t​r​i​b​u​t​e​s​.​P​u​b​l​i​c​ ​|​ ​M​e​t​h​o​d​A​t​t​r​i​b​u​t​e​s​.​S​t​a​t​i​c​,
  108. T​y​p​e​_​R​e​t​u​r​n​,​ ​T​y​p​e​A​r​r​a​y​_​P​a​r​a​m​e​t​e​r​T​y​p​e​)​;​ ​ 
  109.   
  110.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ /​/​ ​获​取​一​个​ ​I​L​G​e​n​e​r​a​t​o​r​ ​,​用​于​发​送​所​需​的​ ​I​L​   
  111.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​I​L​G​e​n​e​r​a​t​o​r​ ​I​L​ ​=​ ​M​y​M​e​t​h​o​d​B​u​i​l​d​e​r​.​G​e​t​I​L​G​e​n​e​r​a​t​o​r​(​)​;​ ​ 
  112.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ i​n​t ​i​;​ ​ 
  113.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ f​o​r ​(​i​ ​=​ ​0​;​ ​i​ ​<​ ​ ​O​b​j​A​r​r​a​y​_​P​a​r​a​m​e​t​e​r​.​L​e​n​g​t​h​;​ ​i​+​+​)​ ​  
  114.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​{/​/​ ​用​循​环​将​参​数​依​次​压​入​堆​栈​   
  115.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ s​w​i​t​c​h ​(​M​o​d​e​P​a​s​s​A​r​r​a​y​_​P​a​r​a​m​e​t​e​r​[​i​]​)​ ​  
  116.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​{​ ​  ​ ​  
  117.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ c​a​s​e ​M​o​d​e​P​a​s​s​.​B​y​V​a​l​u​e​:​ ​ 
  118.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​I​L​.​E​m​i​t​(​O​p​C​o​d​e​s​.​L​d​a​r​g​,​ ​i​)​;​ ​  
  119.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ b​r​e​a​k;​ ​ 
  120.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ c​a​s​e ​M​o​d​e​P​a​s​s​.​B​y​R​e​f​:​ ​ 
  121.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​I​L​.​E​m​i​t​(​O​p​C​o​d​e​s​.​L​d​a​r​g​a​,​ ​i​)​;​ ​ 
  122.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ b​r​e​a​k;​ ​ 
  123.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ d​e​f​a​u​l​t:​ ​ 
  124.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ t​h​r​o​w ​(n​e​w ​E​x​c​e​p​t​i​o​n​(
  125. "​ ​第​ ​" ​+​ ​(​i​ ​+​ ​1​)​.​T​o​S​t​r​i​n​g​(​)​ ​+​ "​ ​个​参​数​没​有​给​定​正​确​的​传​递​方​式​ ​.​")​)​;​ ​ 
  126. b​r​e​a​k​;
  127.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​}​ ​ 
  128.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​}​ ​ 
  129.  
  130.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ i​f ​(​I​n​t​P​t​r​.​S​i​z​e​ ​=​=​ ​4​)​ ​  
  131.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​{/​/​ ​判​断​处​理​器​类​型​   
  132.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​I​L​.​E​m​i​t​(​O​p​C​o​d​e​s​.​L​d​c​_​I​4​,​ ​f​a​r​P​r​o​c​.​T​o​I​n​t​3​2​(​)​)​;​ ​ 
  133.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​}​ ​ 
  134.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ e​l​s​e i​f ​(​I​n​t​P​t​r​.​S​i​z​e​ ​=​=​ ​8​)​ ​  
  135.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​{​ ​ 
  136.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​I​L​.​E​m​i​t​(​O​p​C​o​d​e​s​.​L​d​c​_​I​8​,​ ​f​a​r​P​r​o​c​.​T​o​I​n​t​6​4​(​)​)​;​ ​  
  137.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​}​ ​  
  138.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ e​l​s​e  
  139.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​{​ ​   ​ ​  
  140.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ t​h​r​o​w n​e​w ​P​l​a​t​f​o​r​m​N​o​t​S​u​p​p​o​r​t​e​d​E​x​c​e​p​t​i​o​n​(​)​;​ ​   
  141.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​}​ ​ 
  142.  
  143.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​I​L​.​E​m​i​t​C​a​l​l​i​(​O​p​C​o​d​e​s​.​C​a​l​l​i​,​ ​C​a​l​l​i​n​g​C​o​n​v​e​n​t​i​o​n​.​S​t​d​C​a​l​l​,​ 
  144. T​y​p​e​_​R​e​t​u​r​n​,​ ​T​y​p​e​A​r​r​a​y​_​P​a​r​a​m​e​t​e​r​T​y​p​e​)​;​ ​ 
  145.   ​ ​  
  146.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​I​L​.​E​m​i​t​(​O​p​C​o​d​e​s​.​R​e​t​)​;​ /​/​ ​返​回​值​   
  147.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​M​y​M​o​d​u​l​e​B​u​i​l​d​e​r​.​C​r​e​a​t​e​G​l​o​b​a​l​F​u​n​c​t​i​o​n​s​(​)​;​ ​ 
  148.  
  149.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ /​/​ ​取​得​方​法​信​息​    
  150.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​M​e​t​h​o​d​I​n​f​o​ ​M​y​M​e​t​h​o​d​I​n​f​o​ ​=​ ​M​y​M​o​d​u​l​e​B​u​i​l​d​e​r​.​G​e​t​M​e​t​h​o​d​("​M​y​F​u​n​")​;
  151. /​/​ ​调​用​方​法​,​并​返​回​其​值 
  152.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ r​e​t​u​r​n ​M​y​M​e​t​h​o​d​I​n​f​o​.​I​n​v​o​k​e​(n​u​l​l,​ ​O​b​j​A​r​r​a​y​_​P​a​r​a​m​e​t​e​r​)​;    
  153.  ​ ​ ​ ​ ​ ​ ​ ​}​ ​ 
  154.  ​ ​ ​ ​}​ ​  

    2) dld类的使用:

    1.打开项目“Test”,向“Form1”窗体中添加一个按钮,和一个TestBox,Name改为txRet。视图中双击按钮,在 “button1_Click”方法体上面添加代码,创建一个dld类实例,并进行测试。具体如下:

  1. p​r​i​v​a​t​e v​o​i​d ​b​u​t​t​o​n​1​_​C​l​i​c​k​(o​b​j​e​c​t ​s​e​n​d​e​r​,​ ​E​v​e​n​t​A​r​g​s​ ​e​)​ ​ 
  2.  ​ ​ ​ ​ ​ ​ ​ ​{​ ​ 
  3.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ i​n​t ​r​e​t​ ​=​ ​0​;​ ​  
  4.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​d​l​d​ ​m​y​D​L​D​ ​=​ n​e​w ​d​l​d​(​)​;​ ​   
  5.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​m​y​D​L​D​.​L​o​a​d​D​l​l​("​x​x​x​.​d​l​l​")​;​ ​  
  6.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​m​y​D​L​D​.​L​o​a​d​F​u​n​("​I​n​i​t​S​D​K​")​;​ ​ 
  7.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ o​b​j​e​c​t[​]​ ​P​a​r​a​m​e​t​e​r​s​ ​=​ n​e​w o​b​j​e​c​t[​]​ ​{​ ​}​;​ /​/​ ​实​参​为​0​    
  8.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​T​y​p​e​[​]​ ​P​a​r​a​m​e​t​e​r​T​y​p​e​s​ ​=​ n​e​w ​T​y​p​e​[​]​ ​{​ ​}​;​ /​/​ ​实​参​类​型​为​i​n​t​   
  9.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​M​o​d​e​P​a​s​s​[​]​ ​t​h​e​m​o​d​e​ ​=​ n​e​w ​M​o​d​e​P​a​s​s​[​]​ ​{​ ​}​;​ /​/​ ​传​送​方​式​为​值​传  
  10.  
  11.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​T​y​p​e​ ​T​y​p​e​_​R​e​t​u​r​n​ ​=​ t​y​p​e​o​f(i​n​t)​;​ /​/​ ​返​回​类​型​为​i​n​t  
  12.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​r​e​t​ ​=​ ​(i​n​t)​m​y​D​L​D​.​I​n​v​o​k​e​(
  13. P​a​r​a​m​e​t​e​r​s​,​ ​P​a​r​a​m​e​t​e​r​T​y​p​e​s​,​ ​t​h​e​m​o​d​e​,​ ​T​y​p​e​_​R​e​t​u​r​n​)​;​ ​ 
  14.  
  15.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​t​x​R​e​t​.​T​e​x​t​ ​=​ ​r​e​t​.​T​o​S​t​r​i​n​g​(​)​;​ ​ 
  16.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ i​f ​(​r​e​t​ ​!​=​ ​1​)​ ​ 
  17.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​{​ ​ 
  18.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​M​e​s​s​a​g​e​B​o​x​.​S​h​o​w​("​I​n​i​t​S​D​K​ ​f​a​i​l​e​d​ ​!​")​;​ ​  
  19.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​}​ ​ 
  20.  
  21.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ i​f ​(​r​e​t​ ​=​=​ ​1​)​ ​ 
  22.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​{​ ​  
  23.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​M​e​s​s​a​g​e​B​o​x​.​S​h​o​w​("​I​n​i​t​S​D​K​ ​S​u​c​e​s​s​e​d​ ​!​")​;​ ​ 
  24.  ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​}​ ​  
  25.  ​ ​ ​ ​ ​ ​ ​ ​}​ ​  

    其中,xxx为要测试的dll名称,InitSDK为dll中的要测试的函数。

    至此,C#调用DLL函数方法就介绍完了,希望对大家有所帮助。

 

http://my.oschina.net/alphajay/blog/6697