C# dll 호출

17785 단어 C#.net

.net dll 소개


dll 파일은 윈도우즈에서 보통 동적 링크 라이브러리 파일을 가리키지만.Net 플랫폼에서 dll은 위탁 관리 코드로 같은 코드를 공유하기 위한 것이지만 전통적인 의미의 동적 링크 라이브러리는 아니다.
에 있습니다.NET에서 프로그램 집합의 개념을 도입했는데 컴파일러를 통해 CLR이 더욱 컴파일하고 실행할 수 있도록 하는 중간 산물을 말한다. WINDOWS 시스템에서 이것은 일반적으로 다음과 같다.dll, 혹은.exe의 형식입니다.그래서Net에서 dll 파일은 프로그램 집합이고 클래스 라이브러리라고도 부르며 트랜잭션 코드입니다.Net은 동적 링크 라이브러리처럼 인용할 수 있지만, C 프로그램 등 이 dll을 직접 호출할 수 없습니다.
본문을 총결하였다.Net 플랫폼에서 호출.dll 라이브러리와 동적 링크 라이브러리 (로컬 dll,native code) 파일의 기본 방법입니다.

.Net 프로그램 세트(DLL 라이브러리 파일) 호출


.Net 프로그램 세트 직접 참조


비주얼 스튜디오에서 라이브러리를 인용하는 것은 매우 편리하다. 라이브러리 내의 클래스와 함수를 직접 조회할 수 있을 뿐만 아니라 인용된 함수를 스마트하게 보완할 수 있다.
  • 솔루션 자원 관리자에서 "인용"=> 오른쪽 키=> 인용 추가=> 인용할 클래스 라이브러리 탐색
  • 코드 앞부분에 using 문구로 라이브러리의 명칭 공간을 인용한다(이렇게 하지 않아도 되지만 함수를 인용할 때 긴 이름을 입력해야 한다)
  • 그리고 코드에서 라이브러리 내의 함수를 직접 호출
  • .NET는 반사된 DLL 라이브러리 파일을 사용하여 프로그램 세트를 동적으로 로드 및 언로드합니다.


    반사는 패키지된 프로그램 세트, 모듈 및 유형의 객체(Type 유형)를 제공합니다.반사동태를 사용하여 유형의 실례를 만들고 유형을 기존 대상에 귀속시키거나 기존 대상에서 유형을 가져와 그 방법을 호출하거나 필드와 속성에 접근할 수 있습니다.
    시스템을 도입해야 합니다.Reflection 네임스페이스 단계는 다음과 같습니다.
    Assembly dllx = Assembly.Load("file.dll");
    object obj=dllx.CreateInstance("dllClass");
    //         
    object result=obj.GetType().GetMethod("dllmethod").Invoke(obj,null);
    //        
    object result=obj.GetType().GetMethod("dllmethod").Invoke(obj,a,b);
    

    object는 var로 대체할 수 있습니다.object를 사용하는 효율이 낮습니다. 상기 코드에서 var을 사용하는 것을 권장합니다.
    C#에서는 모든 유형(예정 유형, 사용자 정의 유형, 참조 유형 및 값 유형)이 Object에서 직접 또는 간접적으로 상속됩니다.모든 종류의 값을 Object 형식의 변수에 부여할 수 있습니다.값 유형의 변수를 객체로 변환하는 프로세스를 포장이라고 합니다.객체 유형의 변수를 값 유형으로 변환하는 프로세스를 "상자 분해"라고 합니다. Var는 값을 부여하는 유형에 따라 변수의 유형을 자동으로 설정합니다. 예를 들어 var intinput=5;int intinput = 5, var intinput = "5.5"는string intinput = "5.5"와 같습니다.

    var 사용
  • 정의할 때 초기화해야 합니다.즉 var s = “abcd” 형식이어야 하며 var s; s = “abcd”;
  • 는 안 된다.
  • 초기화가 완료되면 변수에 초기화 값 유형과 다른 값을 부여할 수 없습니다.
  • var 요구는 국부 변수입니다.
  • var을 사용하여 변수를 정의하는 것은object와 달리 효율적으로 강한 유형을 사용하여 변수를 정의하는 것과 완전히 같다.

  • .NET 호출 c 동적 링크 라이브러리(Native dll)


    P/Invoke에서 Native dll 호출


    InteropServices 네임스페이스를 참조해야 합니다.
    using System.Runtime.InteropServices;
    

    단순 P/Invoke 호출


    .NET 호출 P/Invoke는 이 작업을 수행하는 데 가장 일반적인 방법입니다.다른 방법은 Managed Extensions to C++를 사용하여 함수를 포장하는 것입니다(여기서 설명하지 않음).
    예를 들어kernel32를 호출합니다.MSDN의 원형은 다음과 같은 dll의 beep 함수입니다.
    BOOL Beep(DWORD dwFreq, DWORD dwDuration)
    

    에 있습니다.NET가 호출될 때 이 원형을 작성해야 하기 때문에 데이터 형식을 상응하는 것으로 변환해야 한다.NET 유형입니다.
    C#의 경우 DWORD는 4바이트의 정수이기 때문에 int 또는 uint를 C#의 해당 유형으로 사용할 수 있습니다.bool 유형은 Bool에 해당합니다.따라서 C#을 사용하여 다음과 같은 함수 원형을 작성할 수 있습니다.
    public static extern bool Beep(int frequency, int duration);
    

    extern을 사용하여 이 함수가 다른 곳에 있음을 표시합니다.이 원형은 실행할 때 함수를 어떻게 호출하는지 알려 줍니다.이제 원형에 DllImport 속성을 추가하여 실행할 때 이 함수를 찾을 수 있는 위치를 알려 줍니다.
    [DllImport("kernel32.dll")]
    public static extern bool Beep(int frequency, int duration);
    

    프로그램 설명서에 System을 사용해야 합니다.Runtime.InteropServices 네임스페이스 DllImport에서는 Win32의 코드를 호출할 수 있습니다. C#에서 함수는 만 지원합니다.stdcall의 호출 방식입니다. 조정하려면cdecl의 c/c++ 함수입니다. DllImport에서 Calling Convention = Call Convention을 지정해야 합니다.Cdecl。

    윈도우즈와.net 데이터 형식 대응표


    Win32 Types
    Specification
    CLR Type char, INT8, SBYTE, CHAR
    8-bit signed integer System.SByte short, short int, INT16, SHORT
    16-bit signed integer System.Int16 int, long, long int, INT32, LONG32, BOOL, INT
    32-bit signed integer System.Int32 __int64, INT64, LONGLONG
    64-bit signed integer System.Int64 unsigned char, UINT8, UCHAR, BYTE
    8-bit unsigned integer System.Byte unsigned short, UINT16, USHORT, WORD, ATOM, WCHAR, __wchar_t
    16-bit unsigned integer System.UInt16 unsigned, unsigned int, UINT32, ULONG32, DWORD32, ULONG, DWORD, UINT
    32-bit unsigned integer System.UInt32 unsigned __int64, UINT64, DWORDLONG, ULONGLONG
    64-bit unsigned integer System.UInt64 float, FLOAT
    Single-precision floating point System.Single double, long double, DOUBLE
    Double-precision floating point System.Double

    DllImport 속성 사용 방법

  • DllImport는 메소드 선언에만 배치할 수 있음
  • DllImport 속성으로 수식하는 방법에는 extern 수식자
  • 가 있어야 한다
  • DllImport에는 단일 위치 매개 변수가 있습니다. 가져오는 방법의 dll 이름을 포함하는 dllName 매개 변수를 지정합니다
  • DllImport에는
  • CallingConvention 매개변수는 엔트리 점의 호출 규칙을 나타냅니다.CallingConvention이 지정되지 않은 경우 기본값인 CallingConvention이 사용됩니다.Winapi, 즉 __stdcall 는 C#의 기본 호출 방식입니다. 명시적으로 설명할 필요가 없습니다.
  • CharSet 매개변수는 엔트리 점에 사용되는 문자 세트를 나타냅니다.CharSet을 지정하지 않으면 기본값인 CharSet이 사용됩니다.Auto
  • EntryPoint 매개변수는 dll의 엔트리 점 이름을 제공합니다.EntryPoint를 지정하지 않으면 메서드 자체의 이름
  • 이 사용됩니다.
  • ExactSpelling 매개변수는 EntryPoint가 표시된 엔트리 포인트의 맞춤법과 정확히 일치해야 하는지 여부를 나타냅니다.ExactSpelling을 지정하지 않은 경우 기본값false
  • 를 사용합니다.
  • PreserveSig 매개 변수 지시 방법의 서명은 보류되거나 변환되어야 합니다.서명이 변환될 때, HRESULT 반환값과 이 반환값이 있는 Retval이라는 추가 출력 매개 변수의 서명으로 변환됩니다.PreserveSig을 지정하지 않으면 기본값true
  • 를 사용합니다.
  • SetLastError 매개 변수는 Win32의 이전 오류를 유지할지 여부를 나타냅니다.SetLastError를 지정하지 않으면 기본값false
  • 를 사용합니다.

    복합 함수 P/Invoke 호출


    만약 호출할 함수 매개 변수가 바늘이나 주소 변수라면 어떻게 합니까?
    이런 경우 C#에서 제공한 비안전 코드로 해결할 수 있지만, 비위탁 관리 코드이기 때문에 스팸 자원 처리가 잘 되지 않으면 응용 프로그램에 불리하다.따라서 C#에서 제공하는 ref와 out 수식자를 사용하는 것이 좋다.
    예를 들면 다음과 같습니다.int __stdcall FunctionName(unsigned char &param1, unsigned char *param2)
    C#에서 호출하는 방법은 다음과 같습니다.
    [DllImport("file.dll")]
    public static extern int FunctionName(ref byte param1, ref byte param2);
    

    이걸 보면 & 주소 찾기,*전송지침인데 왜ref만 쓰면 돼요?ref는 무거운 짐을 싣는 특성을 가진 수식자로서 주소를 찾을지 전송 지침을 찾을지 자동으로 식별할 수 있다.
    실제 상황에서, 우리는 매개 변수를 이용하여 주소를 전달하는 것이 더 많은지, 아니면 전송수 그룹의 첫 번째 주소에 더 많이 사용하는지.예:byte[] param1 = new param1(6);
    여기에서 우리는 파라메트릭 그룹의 첫 번째 요소를ref로 장식하기만 하면, 그룹의 첫 번째 주소를 전송할 수 있습니다.구체적으로 다음과 같다.
    [DllImport("file.dll")]
    static extern int FunctionName(ref byte param1[1], ref byte param2);
    

    api를 통해 Native 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++와 같은 함수 포인터 호출 방식이 함수를 호출하지 않기 때문에 우리는 다른 방법을 빌려야 한다.연구를 통해 우리는 시스템을 결합하여 사용할 수 있다는 것을 발견했다.Reflection.Emit 및 System.Reflection.Assembly의 클래스와 함수는 우리의 목적에 도달한다.
    자세한 내용은 DLL 동적 호출을 위한 C# 프로그램 연구 문서를 참조하십시오.

    라이브러리 검색 경로

  • 트랜잭션 dll(클래스 라이브러리)의 검색 경로와native dll의 검색 경로가 다르다
  • 검색 경로의 방식은 호출된 dll 라이브러리(클래스 라이브러리인지native dll인지)에 따라 결정되며 호출 프로그램의 위탁 관리 코드 여부와 무관
  • .net CLR은 실행할 때 정확한 Assembly(클래스 라이브러리 dll도 Assembly)를 찾고 Net은 검색 알고리즘을 제공하여 근거로 삼을 수 있다.config 파일에 사용자 정의 검색 경로를 추가합니다.
    검색 순서는 다음과 같습니다.
  • GAC(Global Assembly Cache, Global Program Cache, Global Cache)에서 해당 버전의 DLL을 검색합니다.
  • 프로필(web.config 또는 app.config)에 코드 베이스(assemblyIdentity를 설정하지 않아도 될 것 같다)
  • <configuration>
       <runtime>
          <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
             <dependentAssembly>
                <assemblyIdentity name="myAssembly"
                                  publicKeyToken="32ab4ba45e0a69a1"
                                  culture="neutral" />
                <codeBase version="2.0.0.0"
                          href="om/myAssembly.dll"/>
             dependentAssembly>
          assemblyBinding>
       runtime>
    configuration>
    
  • 응용 프로그램(.exe) 현재 디렉터리
  • 프로필(web.config 또는 app.config)에 privatePath
  • 를 구성합니다.
    <configuration>
       <runtime>
          <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
             <probing privatePath="bin;bin2\subbin;bin3"/>
          assemblyBinding>
       runtime>
    configuration>
    

    OK, CLR은 위에서 1부터 4까지 Assembly를 검색합니다.지정한 버전의 라이브러리 DLL을 검색하지 못하면 프로그램이 이상을 던집니다. 알림: DLL 파일을 찾을 수 없습니다.

    좋은 웹페이지 즐겨찾기