2016-09-23 3 views
0

C++ API가 :바이트 배열이 인식되지

typedef struct 
{ 
    BYTE bCommandCode; 
    BYTE bParameterCode; 

    struct 
    { 
     DWORD dwSize; 
     LPBYTE lpbBody; 
    } 
    Data; 
} 
COMMAND; 

그리고 함수 :

DLL_API DWORD WINAPI ExecuteCommand(LPCSTR, CONST COMMAND, CONST DWORD, LPREPLY); 

그리고 내 C# 동등한 코드 :

public struct Data 
{ 
    public int dwSize; 
    public byte[] lpbBody; 
} 

public struct Command 
{ 
    public byte bCommandCode; 
    public byte bParameterCode; 

    public Data Data; 
} 

[DllImport(@"api.dll", CallingConvention = CallingConvention.Winapi)] 
public static extern int ExecuteCommand(string port, Command command, int timeout, ref Reply reply); 

답글 구조체는 여기에 필요하지 않습니다.

내가 전화 ExecuteCommand를 : 나는 바이트 [] BDATA가 올바르게 전혀 인식하지 못하는 것을 볼

Command command = new Command(); 
command.bCommandCode = 0x10; 
command.bParameterCode = 0x10; 

byte[] bData = { 0xff, 0xff }; 
command.Data.dwSize = bData.Length; 
command.Data.lpbBody = bData; 

Reply reply = new Reply(); 
var result = ExecuteCommand("COM1", command, 5000, ref reply); 

나는 C에서 로그를 볼 ++ DLL. 내가 뭘 잘못하고 있니? 어쩌면이 정의가 올바르지 않을 수 있습니다 : public byte [] lpbBody? 구조체의 LPBYTE 배열을 C++ 메서드에 전달할 수 있습니까?

답변

1

관리 대상 개체 (예 : 문제가있는 바이트 배열)를 할당하면 관리되는 힙의 특정 주소에 매핑되며 관리되는 힙은 특정 관리되지 않는 메모리 주소에 매핑됩니다. 관리되는 주소와 관리되지 않는 주소 간의 매핑은 GC가 작동 할 때 변경 될 수 있습니다. 관리되지 않는 메모리 청크를 이동하여 할당 된 관리되지 않는 메모리 공간을 조각에서 분리하기 때문입니다.

byte []를 참조로 사용하여 관리되지 않는 API를 호출하면 마샬링 프로세스는 기본적으로 바이트 배열 개체의 관리되지 않는 주소를 네이티브 API로 전달합니다. 따라서 바이트 배열의 메모리 주소가 앞에서 설명한 디 프랙 션 (de-fragmentation)으로 인해 더 이상 사용하려고 시도하지 않을 때 더 이상이를 가리 키지 않을 가능성이 높습니다.

나는 이것이 진실로 당신이 경험하고있는 것이라고 믿습니다.
는 다행히이 문제를 쉽게 해결할 수 있습니다

GCHandle pinned = GCHandle.Alloc(bData, GCHandleType.Pinned); 
IntPtr arrPtr = pinned.AddrOfPinnedObject(); 

첫 번째 줄은 관리 바이올린하지 않도록 GC를 알려줍니다 -이 object> 관리되지 않는 매핑. 두 번째는 자체에 대해 말합니다. 이제 C# 측의 'Data'구조체를 byte []
(C++ 측을 변경할 필요가 없음) 대신 IntPtr을 유지하도록 변경하면됩니다.

public struct Data 
{ 
    public int dwSize; 
    public IntPtr lpbBody; 
} 

하면 GCHandle 개체 함께 할 때 GCHandle.Free() 메서드를 호출해야합니다.

마샬링 된 유형을 MarshalAsAttribute 클래스로 표시하려고하고이 예제에서 간단히 생략했으면 좋겠습니다.

+0

아니요, MarshalAsAttribute를 사용하지 않습니다. 어디에서 사용해야합니까? – Anton23

+0

클래스/구조체 및 필드 꼭대기. 인터넷 메이트에있는 많은 자습서. 마샬링에 대해 읽고 .NET에서 작동하는 방법을 제안합니다. –

+0

GCHandle.Alloc 작품! 고마워요! @ 페리 – Anton23

관련 문제