2011-12-03 12 views
8

Hy vọng rằng đây không phải là quá khó hiểu cho SO, nhưng xem xét P sau/Gọi chữ ký:Làm thế nào một SafeHandle có thể được sử dụng trong một chữ ký P/Invoke yêu cầu một con trỏ null trong một số trường hợp?

[DllImport("odbc32.dll", CharSet = CharSet.Unicode)] 
internal static extern OdbcResult SQLAllocHandle(
    OdbcHandleType HandleType, 
    IntPtr InputHandle, 
    ref IntPtr OutputHandlePtr); 

Tôi muốn thiết kế lại chữ ký này để sử dụng SafeHandles, như sau:

[DllImport("odbc32.dll", CharSet = CharSet.Unicode)] 
internal static extern OdbcResult SQLAllocHandle(
    OdbcHandleType HandleType, 
    MySafeHandle InputHandle, 
    ref MySafeHandle OutputHandlePtr); 

Tuy nhiên, according to MSDN, đối số InputHandle phải là một con trỏ rỗng khi đối số HandleType là SQL_HANDLE_ENV và một con trỏ không null khác.

Làm cách nào để nắm bắt các ngữ nghĩa đó trong một chữ ký P/Invoke? Vui lòng bao gồm ví dụ trang web trong câu trả lời của bạn. Giải pháp hiện tại của tôi là sử dụng hai chữ ký.

Trả lời

4

SafeHandle là một lớp học để bạn có thể vượt qua null thay vì thực tế SafeHandle. Một tham chiếu null được sắp xếp như một con trỏ null trong P/Invoke.

SafeHandle handle = new SafeHandle(); 
OdbcResult result= SQLAllocHandle(OdbcHandleType.SQL_HANDLE_ENV, null, ref handle); 
+2

Cũng có thể khai báo tham số 'out SafeHandle'. –

+5

Không hoạt động ở đây, tôi nhận được 'ArgumentNullException' từ' System.StubHelpers.StubHelpers.SafeHandleAddRef (SafeHandle pHandle, Boolean & success) '. – ordag

+0

Có, @ shf301, điều này không hoạt động trong P/Gọi điện. Bạn có thử nó không? – jnm2

1

The answer by shf301 đi null cho đối số đầu vào InputHandle. Điều này không làm việc trên hầu hết các API (có thể nó bằng cách nào đó không cho vấn đề cụ thể của OP, cho rằng họ chấp nhận câu trả lời).

tôi sử dụng mô hình này:

[SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode = true)] 
public class RegionHandle : SafeHandleZeroOrMinusOneIsInvalid 
{ 
    private RegionHandle() : base(true) {} 

    public static readonly RegionHandle Null = new RegionHandle(); 

    [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] 
    override protected bool ReleaseHandle() 
    { 
     return Region.DeleteObject(handle); 
    } 
} 

Nó có nghĩa là tôi có thể làm điều này để vượt qua một tay cầm null:

SomeApi(RegionHandle.Null); 

Nó tương tự như thế nào có một thành viên tĩnh IntPtr.Zero.

Các vấn đề liên quan