이 항목에서는 관리되지 않는 함수에 액세스하는 방법을 설명하고 관리 코드에서 메서드 정의에 주석을 추가하는 여러 특성 필드를 소개합니다. 를 생성하는 방법을 보여 주는 예제입니다. 플랫폼 호출과 함께 사용할 NET 기반 선언은 플랫폼 호출을 사용하여 데이터 마샬링을 참조하세요.
관리 코드에서 관리되지 않는 DLL 함수에 액세스하려면 먼저 함수의 이름과 함수를 내보내는 DLL의 이름을 알아야 합니다. 이 정보를 사용하여 DLL에서 구현되는 관리되지 않는 함수에 대한 관리되는 정의를 작성할 수 있습니다. 또한 플랫폼 호출이 함수를 생성하고 함수로의 데이터 전송 방식을 조정할 수 있습니다.
비고
문자열을 할당하는 Windows API 함수를 사용하면 다음과 같은 LocalFree메서드를 사용하여 문자열을 해제할 수 있습니다. 플랫폼 호출은 이러한 매개 변수를 다르게 처리합니다. 플랫폼 호출의 경우 매개변수를 IntPtr 형식 대신 String 형식으로 만드십시오.
System.Runtime.InteropServices.Marshal 클래스가 제공하는 메서드를 사용하여 타입을 문자열로 수동 변환하고, 이를 수동으로 해제합니다.
선언 기본 사항
다음 예제에서 볼 수 있듯이 관리되지 않는 함수에 대한 관리되는 정의는 언어에 따라 다릅니다. 자세한 코드 예제는 플랫폼 호출 예제를 참조하세요.
Friend Class NativeMethods
Friend Declare Auto Function MessageBox Lib "user32.dll" (
ByVal hWnd As IntPtr,
ByVal lpText As String,
ByVal lpCaption As String,
ByVal uType As UInteger) As Integer
End Class
Visual Basic 선언에 DllImportAttribute.BestFitMapping, DllImportAttribute.CallingConvention, DllImportAttribute.ExactSpelling, DllImportAttribute.PreserveSig, DllImportAttribute.SetLastError 또는 DllImportAttribute.ThrowOnUnmappableChar 필드를 적용하려면 DllImportAttribute 문 대신 Declare 특성을 사용해야 합니다.
Imports System.Runtime.InteropServices
Friend Class NativeMethods
<DllImport("user32.dll", CharSet:=CharSet.Auto)>
Friend Shared Function MessageBox(
ByVal hWnd As IntPtr,
ByVal lpText As String,
ByVal lpCaption As String,
ByVal uType As UInteger) As Integer
End Function
End Class
using System;
using System.Runtime.InteropServices;
internal static class NativeMethods
{
[DllImport("user32.dll")]
internal static extern int MessageBox(
IntPtr hWnd, string lpText, string lpCaption, uint uType);
}
using namespace System;
using namespace System::Runtime::InteropServices;
[DllImport("user32.dll")]
extern "C" int MessageBox(
IntPtr hWnd, String* lpText, String* lpCaption, unsigned int uType);
정의 조정
명시적으로 설정하든 그렇지 않든 특성 필드는 관리 코드의 동작을 정의하는 작업에 있습니다. 플랫폼 호출은 어셈블리에 메타데이터로 존재하는 다양한 필드에 설정된 기본값에 따라 작동합니다. 하나 이상의 필드 값을 조정하여 이 기본 동작을 변경할 수 있습니다. 대부분의 경우 값을 설정하는 데 사용합니다 DllImportAttribute .
다음 표에서는 플랫폼 호출과 관련된 전체 특성 필드 집합을 나열합니다. 각 필드에 대해 테이블에는 기본값과 이러한 필드를 사용하여 관리되지 않는 DLL 함수를 정의하는 방법에 대한 정보 링크가 포함되어 있습니다.
| 분야 | 설명 |
|---|---|
| BestFitMapping | 최적 매핑을 사용하거나 사용하지 않도록 설정합니다. |
| CallingConvention | 메서드 인수 전달에 사용할 호출 규칙을 지정합니다. 기본값은 WinAPI32비트 Intel 기반 플랫폼에 해당하는 __stdcall 것입니다. |
| CharSet | 이름 맹글링 및 문자열 인수를 함수에 전달하는 방식을 제어합니다. 기본값은 CharSet.Ansi입니다. |
| EntryPoint | 호출할 DLL 진입점을 지정합니다. |
| ExactSpelling | 문자 집합에 해당하도록 진입점을 수정해야 하는지 여부를 제어합니다. 기본값은 프로그래밍 언어에 따라 다릅니다. |
| PreserveSig | 관리되는 메서드 시그니처를 HRESULT를 반환하고 반환 값에 대한 추가 [out, retval] 인수가 있는 관리되지 않는 서명으로 변환해야 하는지 여부를 제어합니다. 기본값은 (서명을 변환해서는 안 됨)입니다 true . |
| SetLastError | 호출자가 API 함수를 Marshal.GetLastWin32Error 사용하여 메서드를 실행하는 동안 오류가 발생했는지 여부를 확인할 수 있습니다. Visual Basic에서 기본값은 trueC# 및 C++이며 기본값은 false. |
| ThrowOnUnmappableChar | 매핑할 수 없는 유니코드 문자가 ANSI "?" 문자로 변환될 때 예외를 throw하는 제어입니다. |
자세한 참조 정보는 을 참조하세요 DllImportAttribute.
플랫폼 호출 시 보안 고려 사항
Assert 열거형의 Deny, PermitOnly, 및 SecurityAction 멤버를 스택 워크 한정자라고 합니다. 이러한 멤버는 플랫폼 호출 선언 및 COM IDL(인터페이스 정의 언어) 문에서 선언적 특성으로 사용되는 경우 무시됩니다.
플랫폼 호출 예제
이 섹션의 플랫폼 호출 샘플에서는 스택 워크 수정자와 함께 RegistryPermission 특성을 사용하는 방법을 보여 줍니다.
다음 예제 SecurityActionAssert에서는 , Deny및 PermitOnly 한정자가 무시됩니다.
[DllImport("MyClass.dll", EntryPoint = "CallRegistryPermission")]
[RegistryPermission(SecurityAction.Assert, Unrestricted = true)]
private static extern bool CallRegistryPermissionAssert();
[DllImport("MyClass.dll", EntryPoint = "CallRegistryPermission")]
[RegistryPermission(SecurityAction.Deny, Unrestricted = true)]
private static extern bool CallRegistryPermissionDeny();
[DllImport("MyClass.dll", EntryPoint = "CallRegistryPermission")]
[RegistryPermission(SecurityAction.PermitOnly, Unrestricted = true)]
private static extern bool CallRegistryPermissionDeny();
그러나 다음 예제의 Demand 한정자는 허용됩니다.
[DllImport("MyClass.dll", EntryPoint = "CallRegistryPermission")]
[RegistryPermission(SecurityAction.Demand, Unrestricted = true)]
private static extern bool CallRegistryPermissionDeny();
SecurityAction 한정자는 플랫폼 호출 호출을 포함하는(래핑) 클래스에 배치된 경우 올바르게 작동합니다.
[RegistryPermission(SecurityAction.Demand, Unrestricted = true)]
public ref class PInvokeWrapper
{
public:
[DllImport("MyClass.dll", EntryPoint = "CallRegistryPermission")]
private static extern bool CallRegistryPermissionDeny();
};
[RegistryPermission(SecurityAction.Demand, Unrestricted = true)]
class PInvokeWrapper
{
[DllImport("MyClass.dll", EntryPoint = "CallRegistryPermission")]
private static extern bool CallRegistryPermissionDeny();
}
SecurityAction 한정자는 플랫폼 호출의 호출자에 배치되는 중첩된 시나리오에서도 올바르게 작동합니다.
{
public ref class PInvokeWrapper
public:
[DllImport("MyClass.dll", EntryPoint = "CallRegistryPermission")]
private static extern bool CallRegistryPermissionDeny();
[RegistryPermission(SecurityAction.Demand, Unrestricted = true)]
public static bool CallRegistryPermission()
{
return CallRegistryPermissionInternal();
}
};
class PInvokeScenario
{
[DllImport("MyClass.dll", EntryPoint = "CallRegistryPermission")]
private static extern bool CallRegistryPermissionInternal();
[RegistryPermission(SecurityAction.Assert, Unrestricted = true)]
public static bool CallRegistryPermission()
{
return CallRegistryPermissionInternal();
}
}
COM Interop 예제
이 섹션의 RegistryPermission COM 상호 운용성 샘플에서는 스택 워크 수정자와 함께 속성을 사용하는 방법을 보여줍니다.
다음 COM interop 인터페이스 선언은 이전 섹션의 Assert플랫폼 호출 예제와 마찬가지로 , Deny및 PermitOnly 한정자를 무시합니다.
[ComImport, Guid("12345678-43E6-43c9-9A13-47F40B338DE0")]
interface IAssertStubsItf
{
[RegistryPermission(SecurityAction.Assert, Unrestricted = true)]
bool CallRegistryPermission();
[FileIOPermission(SecurityAction.Assert, Unrestricted = true)]
bool CallFileIoPermission();
}
[ComImport, Guid("12345678-43E6-43c9-9A13-47F40B338DE0")]
interface IDenyStubsItf
{
[RegistryPermission(SecurityAction.Deny, Unrestricted = true)]
bool CallRegistryPermission();
[FileIOPermission(SecurityAction.Deny, Unrestricted = true)]
bool CallFileIoPermission();
}
[ComImport, Guid("12345678-43E6-43c9-9A13-47F40B338DE0")]
interface IAssertStubsItf
{
[RegistryPermission(SecurityAction.PermitOnly, Unrestricted = true)]
bool CallRegistryPermission();
[FileIOPermission(SecurityAction.PermitOnly, Unrestricted = true)]
bool CallFileIoPermission();
}
Demand 수정자는 다음 예제에서 보여 주듯이 COM 상호 운용 인터페이스 선언 시나리오에서는 허용되지 않습니다.
[ComImport, Guid("12345678-43E6-43c9-9A13-47F40B338DE0")]
interface IDemandStubsItf
{
[RegistryPermission(SecurityAction.Demand, Unrestricted = true)]
bool CallRegistryPermission();
[FileIOPermission(SecurityAction.Demand, Unrestricted = true)]
bool CallFileIoPermission();
}
참고하십시오
.NET