cgo 로 cgo 에 사용 할 C 호 환 구조 체 생 성

가설 (완전한 가설 이 아 닙 니 다. 데모 가 있 습 니 다) Go 와 다른 C 구조 체 메모리 프로그램 을 연결 하 는 프로그램 을 만 들 고 있 습 니 다.이러한 구 조 는 시스템 호출 의 결과 일 수도 있 고 라 이브 러 리 가 제공 하 는 순수한 정보 적 내용 일 수도 있다.어떤 경우 에 도 이 구 조 를 프로그램 패키지 사용자 에 게 전달 하여 이 구 조 를 사용 하여 작업 을 수행 할 수 있 도록 하고 싶 습 니 다.가방 에 서 는 cgo 가 제공 하 는 C 타 입 을 직접 사용 할 수 있 습 니 다.그러나 이 는 좀 짜증 이 납 니 다.따라서 네 이 티 브 고 구조 체 를 어떤 식 으로 든 사용 해 야 한다.
C 구조 체 를 수 동 으로 정의 하 는 방식 입 니 다.이것 은 두 가지 결점 이 있다.이것 은 너무 무미건조 하 다 (실수 하기 쉽다). 그리고 C 와 똑 같은 메모리 레이아웃 을 얻 을 수 있다 는 것 을 보장 할 수 없다 (후 자 는 일반적으로 중요 하지 않다).다행히도 cgo -godefs 기능 을 사용 하여 구조 체 성명 을 자동 으로 생 성 하 는 더 좋 은 방법 이 있 습 니 다.생 성 결과 가 항상 완벽 한 것 은 아니 지만, 당신 에 게 가장 큰 수익 을 가 져 다 줄 수 있 습 니 다.
사용 -godefs 의 시작 점 은 특수 한 cgo Go 원본 파일 입 니 다. 이 파일 은 일부 Go 형식 을 C 형식 으로 표시 해 야 합 니 다.예 를 들 면:
// +build ignore
package kstat
// #include 
import "C"

type IO C.kstat_io_t
type Sysinfo C.sysinfo_t

const Sizeof_IO = C.sizeof_kstat_io_t
const Sizeof_SI = C.sizeof_sysinfo_t

이러한 상수 들 은 실제 와 비교 하 는 것 을 좋아 하 는 사람 에 게 유용 하 며, 고 유형의 unsafe.Sizeof() 과 C 유형의 크기 가 일치 하 는 지 뒤에서 비교 검사 할 수 있다.
실행 go tool cgo -godefs .go 은 내 보 내기 필드 와 모든 내용 을 가 진 표준 Go 형식 을 표준 출력 으로 인쇄 합 니 다.그리고 파일 에 저장 해서 사용 할 수 있 습 니 다.C 형식 이 바 뀔 수 있다 고 생각한다 면 생 성 된 파일 을 남 겨 두 어야 합 니 다. 그러면 파일 을 다시 만 드 는 데 많은 번 거 로 움 을 피 할 수 있 습 니 다.C 형식 이 기본적으로 고정 되 어 있 으 면 godoc 를 사용 하여 생 성 된 출력 에 대해 설명 할 수 있 습 니 다.cgo 는 형식 일치 문 제 를 고려 하여 원 초적 인 C 구조 에 존재 하 는 padding 도 출력 에 삽입 합 니 다.
만약 원시 적 인 C 구조 체 가 Go 에서 재건 되 지 않 는 다 면 cgo 는 어떻게 할 지 모 르 겠 습 니 다.예 를 들 어 Go 는 padding 이 필요 하지만 C 는 필요 없습니다.잘못 을 지적 해 줬 으 면 좋 겠 어 요.이것 은 네가 앞으로 이 sizeof 들 을 검사 해 야 할 이유 중의 하나 이다.-godefs 가장 큰 제한 은 cgo 가 일반적으로 가지 고 있 는 제한 과 같다 는 것 이다. 그것 은 C 연합 유형 (union) 에 대한 진정한 지지 가 없다. 왜냐하면 Go 는 확실히 이것 이 없 기 때문이다.만약 당신 의 C 구조 체 에 연합 이 있다 면, 당신 은 스스로 그것들 을 어떻게 처리 하 는 지 알 아야 합 니 다.나 는 cgo 가 이것 을 크기 가 적당 한 uint 8 배열 로 바 꿀 것 이 라 고 믿 지만, 이것 은 실제 방문 내용 에 그다지 유용 하지 않다.
여기에 두 가지 문제 가 있다.다른 구조 체 유형 이 새 겨 진 구조 체 가 있다 고 가정 하 십시오.
struct cpu_stat {
   struct cpu_sysinfo cpu_sysinfo;
   struct cpu_syswait cpu_syswait;
   struct vminfo cpu_vminfo;
}

주 구조 체 형식 전에 끼 워 넣 은 구조 형식의 Go 버 전 을 만 드 는 데 도움 을 주어 야 합 니 다.
type Sysinfo C.struct_cpu_sysinfo
type Syswait C.struct_cpu_syswait
type Vminfo  C.struct_cpu_vminfo

type CpuStat C.struct_cpu_stat

그리고 cgo 는 올 바른 내 장 된 Go 구조의 Cpustat 구 조 를 만 들 수 있 습 니 다.이렇게 하지 않 으 면 Cpustat 구조 유형 을 얻 을 수 있 습 니 다. 이 구조 유형 은 불완전한 유형 정 보 를 가지 고 있 습 니 다. 그 중에서 Sysinfo 등 필드 는 _Ctype_… 라 는 이름 의 정의 되 지 않 은 유형 을 참조 합 니 다.
참고 로 저 는 여기 서 Sysinfo 가 아니 라 Cpu_sysinfo 를 말 합 니 다.cgo 는 구조 필드 이름 에서 흔히 볼 수 있 는 접 두 사 를 삭제 할 수 있 습 니 다.나 는 그것 의 알고리즘 이 어떤 것 인지 모 르 지만, 적어도 유용 하 다.
두 번 째 문 제 는 익명 구조 가 박 혀 있다 는 것 이다.
struct mntinfo_kstat {
   ....
   struct {
      uint32_t srtt;
      uint32_t deviate;
   } m_timers[4];
   ....
}

불 행 히 도 cgo 는 이런 문 제 를 처리 할 수 없다.구체 적 으로 는 issue 5253 을 볼 수 있 습 니 다. 두 가지 선택 이 있 습 니 다. 첫 번 째 는 제안 한 CL 복 구 를 사용 하 는 것 입 니 다. 이것 은 현재 src / cmd / cgo / gcc. go 에 적용 되 고 일 할 수 있 습 니 다 (저 에 게).Go 도구 체인 (또는 CL 이 더 이상 적용 되 지 않 거나 작 동 하지 않 을 경우) 을 구축 하지 않 으 려 면 다른 솔 루 션 은 새로운 C 헤더 파일 을 만 드 는 것 입 니 다. 이 파일 은 전체 구조 체 의 변 체 를 가지 고 있 으 며, 서명 구조 체 를 만들어 구조 체 의 익명 화 를 제거 합 니 다.
struct m_timer {
   uint32_t srtt;
   uint32_t deviate;
}

struct mntinfo_kstat_cgo {
   ....
   struct m_timer m_timers [4];
   ....
}

그리고 당신 의 Go 파일 에서
...
// #include "myhacked.h"
...

type MTimer C.struct_m_timer
type Mntinfo C.struct_mntinfo_kstat_cgo

당신 이 틀 리 지 않 는 한 두 C 구조 체 는 똑 같은 크기 와 구 조 를 가지 고 서로 완전히 호 환 되 어야 합 니 다.이제 버 전에 서 사용 할 수 있 습 니 다 -godefs. 앞의 문제 1 의 처리 에 따라 m_timer 명확 한 Go 유형 을 만들어 야 한 다 는 것 을 기억 하 세 요.만약 당신 이 떠 있다 면 (당신 이 이 내용 을 다시 생 성 할 필요 가 없다 고 생각 합 니 다) 생 성 된 Go 파일 에서 이 과정 을 반전 시 키 고 MTimer 형식 을 구조 체 에 익명 화 할 수 있 습 니 다 (Go 는 익명 구조 체 에 좋 은 지원 을 하기 때 문 입 니 다).실제 내용 을 바 꾸 지 않 고 형식 성명 만 바 꾸 었 기 때문에 결 과 는 원본 레이아웃 과 같 아야 합 니 다.
PS: -godefs 의 입력 파일 은 godefs 생 성 에 만 사용 되 기 때문에 정상 적 이지 않 은 go build 프로 세 스 로 설정 되 었 습 니 다.이 파일 이 go build 구 축 된 원본 코드 에 도 포함 된다 면 Go 형식 여러 곳 에서 정 의 된 구축 오 류 를 얻 을 수 있 습 니 다.필연 적 인 결 과 는 이 파일 과 관련 된 모든 파일 을 패키지 의 일반적인. go 파일 과 같은 디 렉 터 리 에 두 지 않 아 도 된다 는 것 이다.너 는 그들 을 하위 디 렉 터 리 에 두 거나 완전히 독립 된 위치 에 두 어도 된다.
(이 package 줄 이 godefs. go 파일 에서 유일 하 게 해 야 할 일 은 cgo 가 출력 에 인쇄 할 패키지 이름 을 설정 하 는 것 이 라 고 생각 합 니 다.)
via: https://utcc.utoronto.ca/~cks/space/blog/programming/GoCGoCompatibleStructs
저자: Chris Siebenmann 번역자: befovy 교정: polaris 1119
본 고 는 GCTT 오리지널 컴 파일, Go 언어 중문 망 명예 출시

좋은 웹페이지 즐겨찾기