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


    在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

  • 相关阅读:
    window.location 对象所包含的属性
    控制器如何获取一条url中存在多个Id
    js 生成GUID
    JS控制前端控件的显示与隐藏
    ASP.NET CORE根据后台数值在razor页面进行判断单选按钮选中
    Selectize 控件使用以及js执行文件的时间差问题
    理解css中的position属性
    本地预览的vue项目,在githubpage静态展示
    关于img底部空白
    [优化]Steamroller-freecodecamp算法题目
  • 原文地址:https://www.cnblogs.com/MADEIN82/p/1997686.html
Copyright © 2020-2023  润新知