2013-10-24 1 views
0

I는 C DLL에서 내 보낸 다음과 같은 기능이 있습니다 :출력 바이트 배열을 마샬링하는 올바른 방법입니까?

int result = -1; 
byte[] buffer = new byte[2048]; 
int length = buffer.Length; 

result = Simulator.GetAttributeValue(
     tag.NativeId, 
     element_index, 
     attribute_index, 
     buffer, 
     ref length 
    ); 

int[] output = new int[length]; 

for (int i = 0; i < length; i++) 
{ 
    output[i] = buffer[i]; 
} 

return output; 

해봤 또 한가지 :

// C 
BOOL WINAPI GetAttributeValue(
     IN  TAG      * psTag, 
     IN  DWORD      dwEltIdx, 
     IN  DWORD      dwAttrIdx, 
     OUT BYTE      * pbBuffer, 
     IN OUT DWORD     * pdwLen) 

// C# 
[DllImport(Simulator.ASSEMBLY, SetLastError = true, CallingConvention = CallingConvention.StdCall)] 
public extern static int GetAttributeValue(
     IntPtr tag_id, 
     int element_index, 
     int attribute_index, 
     [In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=4)] 
     byte[] data_buffer, 
     [In, Out] 
     ref int data_length 
    ); 

이 내가 SO에 여기에 몇 가지 응답에 따라, 그것을 사용하기 위해 노력하고있어 어떻게 이것은 또한 SO에서 발견 대답을 기반으로합니다

[DllImport(Simulator.ASSEMBLY, SetLastError = true, CallingConvention = CallingConvention.StdCall)] 
public extern static int GetAttributeValue(
     IntPtr tag_id, 
     int element_index, 
     int attribute_index, 
     IntPtr data_buffer, // changed this 
     [In, Out] 
     ref int data_length 
    ); 

// snip 

GCHandle pinned_array = GCHandle.Alloc(buffer, GCHandleType.Pinned); 
IntPtr pointer = pinned_array.AddrOfPinnedObject(); 

result = Simulator.GetAttributeValue(
     tag.NativeId, 
     element_index, 
     attribute_index, 
     pointer, 
     ref length 
    ); 

// snip, copying stuff to output 

pinned_array.Free(); 
return output; 

자, 두 경우 모두, 내 length 제대로 채워 것 같다,하지만 buffer은 항상 비어 있습니다. 나는 P/Invoke와 marshalling에 정통하지 않으므로, 이것이 올바른지 확실하지 않습니다. 이 작업을 수행하는 더 좋은 방법이 있습니까?

+0

다른 모든 것이 실패하면 C++/cli에 래퍼 작성을 고려하십시오. 이렇게 많은 호출을하면 작성하고 디버그하는 것이 더 쉬울 수도 있습니다. –

+0

@ jdv-JandeVaan : 운좋게도 버퍼가있는 API 함수가 두 개뿐입니다. 그렇지 않으면 큰 어려움이 있습니다. 아무도 코드까지는 아무 것도 발견하지 못해서 다행입니다.> _> –

답변

1

두 버전 모두 괜찮 으면 무엇이 잘못되었는지를 추측하기가 어렵습니다. Quack은 정확하게 시뮬레이트하지 않는 "시뮬레이터"와 유사합니다. 태그 ID의 IntPtr이 홀수입니다. 오류 코드가 발생하면 과 같이 합리적인 조치를 취해야합니다.

버퍼를 전달해야하는 C 함수는 일반적으로 골칫거리이며 정확한 버퍼 크기를 추측해야합니다. 2048을 따기는 너무나 추측 할 때 잘못 될 것이라는 희망을 품는다. 이러한 함수의 공통 프로토콜은 두 번 호출해야한다는 것입니다. 먼저 data_length에 대해 의도적으로 낮은 값을 0으로 설정합니다. 그런 다음이 함수는 오류 코드를 반환하고 data_length을 필요한 버퍼 크기로 설정합니다. 그런 다음 올바른 크기의 버퍼로 다시 호출합니다. 이것은 단지 추측 일 뿐이며 문제에 부합합니다.

+0

안녕하세요! "태그 ID"는 단지 불투명 한 구조이며 실제로는 IntPtr입니다. 두 경우 모두 오류가 없기 때문에 명확성을 위해 모든 오류 처리 항목을 제거했습니다. Simulator.ASSEMBLY를 C 실행 파일로 테스트하고 테스트해야 할 수도 있습니다. 올바르게 작동하는지 확인하기 위해서입니다. 아마도 아무 것도 할 수없는 시간을 낭비하는 것일 수도 있습니다! : \ –

+0

확실히 확인해야 할 사항입니다. 의도적으로 일부 배열 요소를 0이 아닌 값으로 설정하고 0으로 다시 설정되는지 확인하는 것도 유용한 테스트입니다. –

관련 문제