64 비트 시스템에서 32 비트 포장 바이너리 데이터를 읽습니다

StackOverflow https://stackoverflow.com/questions/135246

  •  02-07-2019
  •  | 
  •  

문제

나는 포장 된 이진 데이터를 읽는 Python C 확장을 작성하려고 시도하고있다 (스트러크의 스트러크로 저장됨). 모든 것이 32 비트 머신에서 예상대로 작동하지만 (이진 파일은 항상 32 비트 아키텍처에 작성) 64 비트 상자에는 그렇지 않습니다. 이 작업을 수행하는 "선호하는"방법이 있습니까?


게시해야 할 많은 코드이지만 예를 들어 :

struct
{
    WORD    version;
    BOOL    upgrade;
    time_t  time1;
            time_t  time2;
} apparms;

File *fp;
fp = fopen(filePath, "r+b");
fread(&apparms, sizeof(apparms), 1, fp);
return Py_BuildValue("{s:i,s:l,s:l}",
  "sysVersion",apparms.version,
  "powerFailTime", apparms.time1,
  "normKitExpDate", apparms.time2
 );

이제 32 비트 시스템에서 이것은 훌륭하게 작동하지만 64 비트에서는 Time_t 크기가 다릅니다 (32 비트 대 64 비트 길이).


젠장, 당신은 빠릅니다.

패트릭, 나는 원래 구조물 패키지를 사용하기 시작했지만 내 필요에 따라 속도가 느려지는 것을 알았습니다. 게다가 나는 파이썬 확장을 쓸 변명을 찾고있었습니다.

나는 이것이 어리석은 질문이라는 것을 알고 있지만 어떤 유형을 조심해야합니까?

감사.

도움이 되었습니까?

해결책

데이터 유형 (예 : 정수)이 32 비트임을 명시 적으로 지정합니다. 그렇지 않으면 읽을 때 서로 옆에 두 개의 정수가 있다면 64 비트 정수로 읽습니다.

크로스 플랫폼 문제를 다룰 때 조심해야 할 두 가지 주요 사항은 다음과 같습니다.

  1. 큰 소리. 포장 된 데이터가 32 비트 INT로 작성된 경우 읽을 때 모든 코드가 32 비트 int를 명시 적으로 지정해야합니다. 그리고 글쓰기.
  2. 바이트 순서. 코드를 인텔 칩에서 PPC 또는 SPARC로 옮기면 바이트 주문이 잘못됩니다. 현재 아키텍처와 일치하도록 데이터를 가져 와서 바이트 플립을해야합니다. 그렇지 않으면 12 (0x0000000C) 201326592로 읽습니다 (0x0C000000).

바라건대 이것은 도움이됩니다.

다른 팁

데이터 중간에있는 스트러크의 정렬은 항상 문제가되지만 '구조'모듈은이를 수행 할 수 있어야합니다. 그러나 올바르게 얻는 것은 그리 어렵지 않습니다. (한 번) Structs-in-Structs가 어떤 경계를 정렬 한 다음, 그 경계에 패드 (수동으로 'x'지정자와 함께)를 찾으십시오. struct.calcsize ()를 실제 데이터와 비교하여 패딩을 이중화 할 수 있습니다. C 확장을 작성하는 것보다 확실히 쉽습니다.

이와 같은 Py_BuildValue ()를 계속 사용하려면 두 가지 옵션이 있습니다. 컴파일 타임 (기본 유형의 측면에서 'int'또는 'long'또는 'ssize_t')에서 time_t의 크기를 결정한 다음 올바른 형식 문자를 Py_BuildValue에 사용하여 int, int, int, 'i'에 올바른 형식 문자를 사용하십시오. 'l'는 ssize_t의 경우 'l', 'n'. 또는 pyint_fromssize_t ()를 수동으로 사용할 수 있으며,이 경우 컴파일러가 업 캐스트를 수행 한 다음 'O'형식 문자를 사용하여 결과를 py_buildValue에 전달합니다.

구조물에 아키텍처 독립 멤버를 사용하고 있는지 확인해야합니다. 예를 들어 INT는 한 아키텍처에서 32 비트, 다른 아키텍처에서 64 비트 일 수 있습니다. 다른 사람들이 제안한 것처럼 사용하십시오 int32_t 대신 스타일 유형. 구조물에 정렬되지 않은 멤버가 포함 된 경우 컴파일러가 추가 한 패딩을 처리해야 할 수도 있습니다.

교차 아키텍처 데이터의 또 다른 일반적인 문제는 Endianness입니다. 인텔 i386 아키텍처는 작은 엔디언이지만 완전히 다른 기계 (예 : 알파 또는 SPARC)를 읽고 있다면 이것에 대해서도 걱정해야합니다.

Python Struct 모듈은 형식 문자열의 일부로 전달 된 접두사를 사용하여 이러한 두 상황을 처리합니다.

  • @- 기본 크기, 엔지니어 및 정렬을 사용하십시오. i = sizeof (int), l = sizeof (long)
  • = - 기본 엔지니어를 사용하지만 표준 크기와 정렬 (i = 32 비트, L = 64 비트)
  • < - 리틀 엔디안 표준 크기/정렬
    • 빅 엔디안 표준 크기/정렬

일반적으로 데이터가 컴퓨터에서 전달되면 엔디 니스와 크기 / 패딩 형식을 구체적인 것으로 정신해야합니다. "<"또는 ">"을 형식으로 사용하십시오. C 확장 에서이를 처리하려면 처리하려면 코드를 추가해야 할 수도 있습니다.

이진 데이터를 읽기위한 코드는 무엇입니까? 데이터를 적절한 크기의 유형으로 복사하고 있는지 확인하십시오. int32_t 그냥 대신 int.

왜 당신은 사용하지 않습니다 구조 패키지?

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top