2009-11-02 3 views
0
내가 서명으로 쓰기 (..) 메소드를 통해이를 구현하고
[DllImport("kernel32.dll", SetLastError=true)] 
    public static extern unsafe bool WriteFile(IntPtr hFile, void* lpBuffer, uint nNumberOfBytesToWrite, out uint lpNumberOfBytesWritten, IntPtr lpOverlapped); 

: 나는 this (the use of the read counterpart is discussed)보고 배운 것처럼 내 코드에서 while 루프를 구현해야구현에서 Win32 FILEWRITE

Write(IntPtr handleFile, void* bufferData, uint length){ 
    void* buffer = bufferData 
    while (length > 0) 
    { 
     uint wrtn; 
     if (!WriteFile(handle, buffer, len, out wrtn, IntPtr.Zero)) 
     { 
     // Do some error handling 
     } 
     // THIS DOESNT WORK! 
     // I want to move along the buffer to be able to write its remainder... 
     // I tried many variations of this as well, but it seems even '+' is not valid for a void* 
     buffer += wrtn; 
     len -= wrtn; 
    } 
} 

때문에 한 번에 버퍼의 쓰기/읽기가 진행되지 않을 수도 있습니다. 문제가 시작되는 곳입니다 :

바이트를 버퍼의 매개 변수로 사용할 수있는 링크 된 읽기 예제와 달리 void *를 허용하도록 C# 메서드 서명을 유지하려고합니다.

이것은 WriteFile을 한 번 통과 한 후에 아직 작성되지 않은 버퍼의 시작 부분까지 내 void *를 이동해야 함을 의미합니다. 분명히 void *를 쓰는 바이트 수를 유지하는 void로 증가 시켜서이 작업을 수행 할 수 없습니다. void *가 미리 결정된 크기가 아니므로 증가가 불가능하다는 것을 이해하지만 어떻게하면 나는하려고 애쓴다.

+3

System.IO 네임 스페이스와 함께 제공되는 것을 사용할 수있을 때 Win32 API 안전하지 않은 코드를 사용해야하는 이유가 있습니까? –

+0

예, 네이티브 stuff/interop에 대한 지식을 넓히고 .net이 일반적으로 숨 깁니다. 나는 내가 "근본적인"물건 (포인터, ...)이라고 부르는 것을 결코 배우지 못했고, 나는 배우고 싶다. – Kris

+0

@Kris : 포인터 및 저급 항목에 대해 배우고 싶다면 저급 언어 (C, C++, (QT, wxWidgets))를 사용하고 하위 수준 언어. – Bobby

답변

1

bufferbyte*으로 캐스팅하고 증분 할 수 있어야합니다. 무효 포인터에는 크기가 연관되어 있지 않으므로 으로 이동하려는 경우 어떤 방향 으로든 바이트를 일정 바이트만큼 이동하면 다른 유형의 포인터 (해당 유형의 모든 유형)로 캐스팅 한 다음 캐스팅 된 바이트를 사용할 수 있습니다 그래서 같은 포인터 연산, 입력의 크기 :

buffer = (void *)((byte*)buffer + wrtn); 

라인이 상기 바이트 포인터 buffer 캐스트는 * 다음 바이트 wrtn 숫자로 해당 위치의 값을 증가하고, 공극에 다시 새로운 포인터를 던진다. 물론 byte*으로 캐스팅하는 것이 임의의 포인터 연산을 수행하려는 경우 확실한 선택입니다.

또 다른 가능성은 내가 모두 Write의 서명을 변경 고려할 것, 모두 함께 byte*buffer을 치료하고 최후의 제안으로, WriteFile

Write(IntPtr handleFile, void* bufferData, uint length) 
{ 
    byte* buffer = (byte*)bufferData; 
    while (length > 0) 
    { 
     uint wrtn; 
     if (!WriteFile(handle, (void*)buffer, len, out wrtn, IntPtr.Zero)) 
     { 
     // Do some error handling 
     } 
     buffer += wrtn; 
     len -= wrtn; 
    } 
} 

에 당신이 그것을 통과 할 때 void*에 캐스팅하는 것입니다 void* 대신 byte*을 사용하면 C#의 다른 발신자와의 호환성이 향상되고 byte*이 더 적합합니다. 당신은 당신이 그것을 통과 할 때 void*에 위의 그림과 같이 byte* 캐스팅 할 수 있기 때문에 그것은의 WriteFile 네이티브 API의 서명과 일치 만들기에 대해 걱정할 필요가 없습니다.

Write(IntPtr handleFile, byte* bufferData, uint length) 
{ 
    while (length > 0) 
    { 
     uint wrtn; 
     if (!WriteFile(handle, (void*)bufferData, len, out wrtn, IntPtr.Zero)) 
     { 
     // Do some error handling 
     } 
     bufferData+= wrtn; 
     len -= wrtn; 
    } 
} 

아아를, 나는 1에 동의해야 댓글 작성자의 왜 이런 짓을하는? 거기에 많은 스트림 지향 클래스를 사용하여 C#에서 파일 쓰기를 수행하는 더 나은 방법입니다.

+0

나는 당신의 대답에 따라 일할 수 있다고 생각합니다. 물론 미리 요리 한 API를 사용하는 것이 더 쉽습니다. 결국에는 그렇게 할 것이지만, 지금은 새로운 것을 배우기를 원합니다. 나는 항상 "블랙 박스"를 사용하는 것이 아니라 모든 것을 정말로 이해하고 싶은 강한 충동을 가지고 있습니다. 때때로 나는 몇몇 코드를 온라인으로 google로 보내거나, "pros"에 의해 일이 어떻게 이루어지는지를보기 위해 어셈블리를보고 나 자신의 버전을 구현하려고합니다. 이것은 그 중 하나였습니다 ... – Kris

+0

그러면 제 설명이 당신이 더 잘 이해할 수 있기를 바랍니다. @Kris. 그러나 C#에서 포인터 작업을 수행하는 모든 코드를 릴리스하기 전에 포인터와 .NET 관리 메모리 모델에 대해 자세히 읽어보십시오. 바르게하지 않으면 많은 고약한 문제가 발생할 수 있습니다! –

+0

계속 : 제안을 시도한 결과 작동했습니다. 내가 얻지 못하는 한 가지는 컴파일러가 뱉어내는 코드입니다. buffer = buffer + wrtn; 여기서 buffer는 byte * 유형이며 wrtn은 버퍼 + = (byte *) wrtn으로 컴파일됩니다. (.NET 리플렉터). 그러나이 마지막 줄은 컴파일되지 않습니다. 어떻게 그렇게 될 수 있습니까? 그리고 이것을 알면, bufferv + = (void *)와 같은 것이 어떨까요 wrtn; (리플렉터에 의한 출력으로서) 원래 부호화되어있다. (무효 * 연산이 가능하지 않다는 것을 안다.) ... – Kris

관련 문제