C#의 DllImport 사용 방법

12084 단어
DllImport는 System입니다.Runtime.InteropServices 네임스페이스의 속성 클래스로, 관리되지 않는 DLL에서 내보내는 함수에 필요한 호출 정보를 제공합니다.
DllImport 속성은 메서드에 적용되며 엔트리 포인트를 포함하는 dll의 이름을 최소한 입력해야 합니다.DllImport의 정의는 다음과 같습니다.
 
     
[AttributeUsage(AttributeTargets.Method)]
public class DllImportAttribute: System.Attribute
{
   public DllImportAttribute(string dllName) {…} //     dllName
   public CallingConvention CallingConvention; //       
   public CharSet CharSet;                                   //         
   public string EntryPoint;  //     
   public bool ExactSpelling;   //                 ,  false
   public bool PreserveSig;  //              
   public bool SetLastError;  //FindLastError           
   public string Value { get {…} }
}

 
사용 예:
[DllImport("kernel32")]
private static extern long WritePrivateProfileString(string section,string key,string val,string filePath);

이상은 ini 파일을 쓰기 위한 win32api입니다.
이 방식으로 Win32API의 데이터 형식을 호출합니다: DWORD=int 또는 uint, BOOL=bool, 상수=enum, 구조=struct입니다. 
DllImport에서 자동으로 찾는 위치:
1. exe가 있는 디렉터리
2, 시스템 32 디렉토리
3. 환경 변수 디렉터리
따라서 인용된 DLL을 이 세 디렉터리로 복사하기만 하면 경로를 쓰지 않아도 된다.아니면 이렇게 서버할 수 있어요.MapPath (.\bin\*.dll) 웹에서, 응용 프로그램에서, 그리고 나중에 DLL의 절대 경로를 지정하면 정상적으로 불러올 수 있습니다.
이 문제는 제3자 비위탁 관리 DLL 구성 요소를 사용할 때 가장 자주 나타난다. 나도 마찬가지로 이때 발생한 문제이다. Asp.Net
Team의 공식 해결 방안은 다음과 같다. 먼저 당신이 어떤 구성 요소를 인용했는지, 그것이 위탁 관리였는지, 어떤 것이 비위탁 관리였는지 확인해야 한다.위탁 관리는 매우 쉽다. 직접 사용되는 것은 인용이 필요하고 간접적으로 사용하는 것은 bin 디렉터리에 복사해야 한다.위탁 관리가 아닌 처리는 비교적 번거롭다.실제로, 당신은 bin으로 복사하는 데 아무런 도움이 되지 않습니다. 왜냐하면 CLR은 파일을 임시 디렉터리로 복사한 다음에 웹을 실행합니다. 그러나 CLR은 위탁 관리 파일만 복사합니다. 이것은 우리가 위탁 관리가 아닌 dll을 bin에 놓았는데도 모듈을 불러올 수 없다는 것을 알려주는 이유입니다.  
구체적인 방법은 다음과 같습니다.
먼저 C:\DLL인 경우 서버에서 아무 곳이나 새 디렉토리를 만듭니다.
그리고 환경 변수에Path 변수에 이 디렉터리를 추가합니다
마지막으로 모든 관리되지 않는 파일을 C:\DLL로 복사합니다.  
아니면 더 깔끔하게 DLL을 시스템 32 디렉터리에 두세요.
스스로 배치할 수 있는 프로그램에 대해 이렇게 하는 것은 해결책이 아니다. 그러나 만약 우리가 가상 공간을 사용한다면, 우리는 PATH 변수를 등록하거나 DLL을 시스템 32 디렉터리에 복사할 수 없다.동시에 우리는 반드시 우리의 Dll의 물리적 경로를 알지 못한다.
DllImport 안에는 문자열 상수만 사용할 수 있고 Server는 사용할 수 없습니다.MapPath(@ "~/Bin/Judge.dll")로 물리적 경로를 결정합니다.ASP.NET에서 DllImport를 사용하려면 먼저 "using System.Runtime.Interop Services;"그러나 나는 이런'비위탁 관리 Dll'을 사용하는 것이 상당히 느리다는 것을 발견했다. 아마도 나의 방법은 원격 검증이 필요하기 때문일 것이다. 그러나 너무 느리다. 연구를 한 후에 마침내 완벽한 해결 방법을 생각해냈다. 우선 우리가
[DllImport("kernel32.dll")]
private extern static IntPtr LoadLibrary(String path);

[DllImport("kernel32.dll")]
private extern static IntPtr GetProcAddress(IntPtr lib, String funcName);

[DllImport("kernel32.dll")]
private extern static bool FreeLibrary(IntPtr lib);

 
LoadLibrary와 GetProcAddress 함수의 주소를 각각 얻었고, 이 두 함수를 통해 DLL의 함수를 얻었습니다.우리는 먼저 Server를 사용할 수 있다.MapPath (@ "~/Bin/Judge. dll") 에서 DLL의 물리적 경로를 찾은 다음 LoadLibrary로 불러오고, 마지막으로 GetProcAddress로 사용할 함수 주소를 가져옵니다.
다음 사용자 정의 클래스 코드는 LoadLibrary 마운트 및 함수 호출을 완료합니다.
public class DllInvoke 
    {            
        [DllImport("kernel32.dll")] 
        private extern static IntPtr LoadLibrary(String path);

        [DllImport("kernel32.dll")]   
        private extern static IntPtr GetProcAddress(IntPtr lib, String funcName); 

        [DllImport("kernel32.dll")]     
        private extern static bool FreeLibrary(IntPtr lib);     

        private IntPtr hLib;  
 

        public DllInvoke(String DLLPath)   
        {           
            hLib = LoadLibrary(DLLPath);  
        }       

        ~DllInvoke()     
        {        
            FreeLibrary(hLib);  
        }        

        //              
        public Delegate Invoke(String APIName,Type t)     
        {           
            IntPtr api = GetProcAddress(hLib, APIName);   
            return (Delegate)Marshal.GetDelegateForFunctionPointer(api,t);     
        }
    } 

 
다음 코드를 호출합니다
 
     
public delegate int Compile(String command, StringBuilder inf);
            //  
            DllInvoke dll = new DllInvoke(Server.MapPath(@"~/Bin/Judge.dll"));
            Compile compile = (Compile)dll.Invoke("Compile", typeof(Compile));
            StringBuilder inf;
            compile(@“gcc a.c -o a.exe“,inf);//        DLL    Compile  

 
 
여러분은 실제 업무에서 C#를 공부할 때 왜 우리는 이미 존재하는 기능(예를 들어 Windows의 일부 기능, C++에서 이미 작성한 방법)을 위해 코드를 다시 작성해야 합니까? C# 원래 존재했던 기능들을 직접 사용할 수 있는 방법이 있습니까?정답은 긍정적이며 C#의 DllImport를 통해 이러한 기능을 직접 호출할 수 있습니다.DllImport가 있는 이름 공간 using System.Runtime.InteropServices;MSDN에서 DllImportAttribute에 대한 설명은 다음과 같습니다. 이 속성을 방법에 적용할 수 있습니다.DllImportAttribute 속성은 관리되지 않는 DLL에서 내보낸 함수를 호출하는 데 필요한 정보를 제공합니다.최소 요구 사항으로 엔트리 포인트가 포함된 DLL의 이름을 제공해야 합니다.DllImport 속성은 다음과 같이 정의됩니다.
namespace System.Runtime.InteropServices   
 {    
     [AttributeUsage(AttributeTargets.Method)]   
     public class DllImportAttribute: System.Attribute  
     {     
         public DllImportAttribute(string dllName)
         {...}      

         public CallingConvention CallingConvention;   
         public CharSet CharSet;    
         public string EntryPoint;    
         public bool ExactSpelling;     
         public bool PreserveSig;      
         public bool SetLastError;     
         public string Value { get {...} }    
     }   
 }

설명:
1. DllImport는 메소드 선언에만 배치할 수 있습니다.2. DllImport에는 단일 위치 매개 변수가 있습니다. 가져오는 방법의 dll 이름을 포함하는 dllName 매개 변수를 지정합니다.3. DllImport에는 다섯 개의 명명 파라미터가 있다. a, CallingConvention 파라미터는 입구점의 호출 약정을 표시한다.CallingConvention이 지정되지 않은 경우 기본값인 CallingConvention이 사용됩니다.Winapi.b. CharSet 매개변수는 엔트리 포인트에 사용되는 문자 세트를 나타냅니다.CharSet을 지정하지 않으면 기본값인 CharSet이 사용됩니다.Auto.c, EntryPoint 매개변수는 dll의 엔트리 점 이름을 제공합니다.EntryPoint를 지정하지 않으면 메서드 자체의 이름이 사용됩니다.d, ExactSpelling 매개변수는 EntryPoint가 표시된 엔트리 포인트의 맞춤법과 정확히 일치해야 하는지 여부를 나타냅니다.ExactSpelling을 지정하지 않으면 기본값false가 사용됩니다.e, PreserveSig 매개 변수 지시 방법의 서명이 보존되거나 변환되어야 합니다.서명이 변환될 때, HRESULT 반환값과 이 반환값이 있는 Retval이라는 추가 출력 매개 변수의 서명으로 변환됩니다.PreserveSig을 지정하지 않으면 기본값true가 사용됩니다.f, SetLastError 매개변수는 Win32의 이전 오류를 유지할지 여부를 나타냅니다.SetLastError가 지정되어 있지 않으면 기본값false가 사용됩니다.4, 그것은 일회성 속성 클래스입니다.5, 또한 DllImport 속성으로 수식하는 방법에는 extern 수식자가 있어야 한다.
전재 대상:https://www.cnblogs.com/yourpaul/p/6064681.html

좋은 웹페이지 즐겨찾기