zoukankan      html  css  js  c++  java
  • C#引用第三方dll文件

    C#引用第三方dll文件,引用文件声明中参数说明,总结下(以下是看的信息总结下来,我只是搬运工。。)

            [DllImport("Sdtapi.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall,SetLastError = false)]
            public static extern int InitComm(int Port);
    

    参数说明:(1)CharSet (2)CallingConvention (3)SetLastError

    1.CharSet
    CharSet 应该指定的是字符编码,取值:
    CharSet = CharSet.Ansi
    CharSet = CharSet.Auto
    
    2.C# 导入dll时CallingConvention的设置问题
    C#调用非托管的.dll文件方法如下:(参考地址:https://www.xuebuyuan.com/645807.html)
    
     [DllImport("XORDll.dll",
                EntryPoint = "OutEncrypt",
                CharSet = CharSet.Ansi,
                CallingConvention = CallingConvention.StdCall)  
             ]
    
            public static extern int OutEncrypt(string FilePath, string SecretWord); 
    其中CallingConvention.就有五种方式:
    
    CallingConvention = CallingConvention.StdCall
    CallingConvention = CallingConvention.Cdecl
    CallingConvention = CallingConvention.FastCall
    CallingConvention = CallingConvention.ThisCall
    CallingConvention = CallingConvention.Winapi
    
    CallingConvention理解
      CallingConvention理解
    
    有以下几个值可以使用:Cdecl, FastCall, StdCall, ThisCall, Winapi.
    
    Cdecl:由调用者清理栈资源。非常适合用在可变参数的函数调用上,例如printf.
    
    FastCall: Calling convention不支持。
    
    StdCall:由被调用者清理栈资源。这是调用native函数时默认的方式。
    
    ThisCall:第一个参数是this指针,会被存储在ECX寄存器里,而其它的参数会被压栈。这种方式通常用在调用未托管的DLL的方法或类。
    
    Winapi:实际上并不是一个calling convention,实际上会被默认的平台的calling convention替代。例如window上调用,会替换成StdCall,Windows CE.NET上则被替换成Cdecl.
    
    小例子:
    
    using namespace System;
    using namespace System::Runtime::InteropServices;
    public ref class LibWrap
    {
    public:
    
       // CallingConvention.Cdecl must be used since the stack is 
       // cleaned up by the caller.
       // int printf( const char *format [, argument]... )
    
       [DllImport("msvcrt.dll",CharSet=CharSet::Unicode, CallingConvention=CallingConvention::Cdecl)]
       static int printf( String^ format, int i, double d );
    
       [DllImport("msvcrt.dll",CharSet=CharSet::Unicode, CallingConvention=CallingConvention::Cdecl)]
       static int printf( String^ format, int i, String^ s );
    };
    
    int main()
    {
       LibWrap::printf( "
    Print params: %i %f", 99, 99.99 );
       LibWrap::printf( "
    Print params: %i %s", 99, "abcd" );
    }
    
    3.SetLastError

    参考博客园问题:https://q.cnblogs.com/q/75565/

    在调用win32 API时,会用到DllImport特性类,该类中有一个属性是SetLastError,文档在此:
    
    https://msdn.microsoft.com/zh-cn/library/system.runtime.interopservices.dllimportattribute.setlasterror(v=vs.80).aspx
    
    我对该属性大概的理解是,如果将它设为true,那么会在api函数执行完成后调用SetLastError这个API,将api函数执行期间发生的错误代码set到调用者的线程中,调用者可以通过调用Marshal.GetLastWin32Error()来获知api函数返回的错误。
    
    但问题是我尝试把SetLastError设为false,通过传入错误的参数故意令api函数出错,随后我仍然通过Marshal.GetLastWin32Error()得到了错误码,设为true也一样,那这样一来,SetLastError设不设还有什么区别呢?
    

    参考博客园的回答:

    win32的错误代码是使用线程本地存储的,类似于linux下的errno,每个线程只有一个。
    
    也就是说你使用GetLastError得到的是前面刚刚出现的错误代码,如果后面再有错误,就会覆盖掉这个值。
    
    你设置这个属性为true,CLR就会保存下这个值,后面可以使用 Marshal.GetLastWin32Error获得使用PInvoke调用的UnManaged函数的最后一个返回值。
    
    这个问题的关键就是通过PInvoke调用这几个字,因为CLR本身也可能调用win32函数,有可能覆盖掉线程的错误代码。
    
  • 相关阅读:
    hdu 5387 Clock (模拟)
    CodeForces 300B Coach (并查集)
    hdu 3342 Legal or Not(拓扑排序)
    hdu 3853 LOOPS(概率DP)
    hdu 3076 ssworld VS DDD(概率dp)
    csu 1120 病毒(LICS 最长公共上升子序列)
    csu 1110 RMQ with Shifts (线段树单点更新)
    poj 1458 Common Subsequence(最大公共子序列)
    poj 2456 Aggressive cows (二分)
    HDU 1869 六度分离(floyd)
  • 原文地址:https://www.cnblogs.com/newcapecjmc/p/12674484.html
Copyright © 2011-2022 走看看