marshal PtrToStructure 질문드립니다.

안녕하세요.
C에서 구조체를 콜백으로 받아, 데이터를 사용하려고 합니다.

C

typedef Structure item
{
    char *item;
}

typedef Structure itemList
{
    int count;
    item* itemList;
}

cb(itemList);

C#

public structure item
{
    string data;
}

public Structure ItemList
{
    int count
    item[] item;
}

public void cb(IntPtr p)
{
    ItemList list = Marshal.PtrToStructure<ItemList>(p);
    print(list.count) // 정상 
    print(list.item[i].data); // 쓰레기 값 

    item[] item = new Item[count.
}

각 구조체 및 콜백은 위와 같은 형태인데요.
IntPtr로 데이터를 받아 다음과 같이 풀어내면 ItemList 데이터에는 접근이 가능한데, ItemList 값을 찍어보면 정크 값이 출력됩니다.

item 배열에 list.count 만큼 메모리 할당 후 값 출력해 봐도 동일한 문제가 발생하네요.
제 접근 방식이 잘못되었을까요?

조언 부탁드립니다. 감사합니다.

테스트 가능한 전체 소스를 GitHub등을 통해 첨부할 수 있을까요?

extern 정의를 살펴봐야 합니다.

아래 문서 중, 구조체에서 사용되는 문자열을 살펴보세요.

댓글 감사합니다.
개인 프로젝트가 아니라 예제 코드로 질문드려야 하는 점 죄송합니다.
답변 주신 것에 대한 추가 질문 드릴께요.
구조체가 중첩으로 되어 있는 경우, Marshal.PtrToStructure로 풀어내면 itemList안의 item 구조체 멤버 변수까지 접근이 가능한가요?
c 및 c# 의 item 구조체에 int, byte 등 여러 타입을 정의 후 값 할당 후 출력 해도 동일한 문제가 발생하네요.
말씀하신 extern 문제인지, 중첩 구조체의 경우 메모리 할당이 필요한지 갈피를 잡지 못해 추가 질문 드려요.

여러가지 경우가 있을 수 있는데 이는 예제를 통해 문제를 찾기가 어렵습니다.
일단 제가 생각나는 문제들을 대략 이 정도 입니다.
아래 방법들을 시도해보면서 어디가 잘못됐는지 찾는 것이 가장 좋아 보입니다.

  1. IntPtr의 포인터 값이 올바른지(또는 바뀌지는 않았는지)
  2. C#에서 ItemList 구조체의 멤버 순서가 C와 동일한 지
  3. C#의 item 구조체의 길이를 지정할 필요가 있는지
  4. C#의 item 구조체의 data가 문자열 포맷에 의존적인지
  5. C의 구조체 중에 union을 사용하는지

1이 잘못됐으면 두말할 것도 없이 이게 원인일 것이고,
2는 멤버의 순서가 바뀌었을 때 int에 해당하는 크기만큼의 데이터가 우연히도 실제 데이터의 길이와 같을 수 있습니다.
이 경우, count는 제대로 들어온다고 생각할 수 있어요.
3은 C에서 char 배열의 크기를 강제로 줬을 경우 필요할 수도 있는데 여기서는 포인터를 사용하니 아마 아닐 것 같습니다.
4는 C에서 문자열을 의미하는 타입에 의존적인지를 의미합니다. 1바이트 문자열도 있고 2바이트 문자열 같은 것들인데 예제와 같은 char만 사용했다면 이 문제일 확률은 낮습니다.
5. 아마 아닐것 같으나… C 구조체에서 union을 사용하면 선언할 때 C와 똑같이해선 안됩니다만 이 문제도 아닐 것 같네요.

2개의 좋아요

친절한 도움감사드립니다.
말씀해주신 포인트를 면밀히 살펴봐야겠습니다.

1개의 좋아요