【问题标题】:struct.error: unpack requires a buffer of 288 bytes when unpacking c++ structurestruct.error: unpack 解压 c++ 结构时需要 288 字节的缓冲区
【发布时间】:2020-10-24 04:33:44
【问题描述】:

首先,很抱歉,如果这个问题已经被问及并得到了回答,但我认为我的情况与我一直试图寻找的其他答案不同。我对 c++ 也很陌生。

我基本上想创建一个系统,其中 c++ 程序从游戏接收数据并通过套接字将其发送到 python 脚本。此数据作为结构存储在 C++ 中,并作为结构发送。我目前坚持在 python 中接收数据并将其实际放入可读格式。

代码在这里:

结构:

struct SPageFilePhysics
{

    int packetId = 0;
    float gas = 0;
    float brake = 0;
    float fuel = 0;
    int gear = 0;
    int rpms = 0;
    float steerAngle = 0;
    float speedKmh = 0;
    float velocity[3];
    float accG[3];
    float wheelSlip[4];
    float wheelLoad[4];
    float wheelsPressure[4];
    float wheelAngularSpeed[4];
    float tyreWear[4];
    float tyreDirtyLevel[4];
    float tyreCoreTemperature[4];
    float camberRAD[4];
    float suspensionTravel[4];
    float drs = 0;
    float tc = 0;
    float heading = 0;
    float pitch = 0;
    float roll = 0;
    float cgHeight;
    float carDamage[5];
    int numberOfTyresOut = 0;
    int pitLimiterOn = 0;
    float abs = 0;
    float kersCharge = 0;
    float kersInput = 0;
    int autoShifterOn = 0;
    float rideHeight[2];
    float turboBoost = 0;
    float ballast = 0;
    float airDensity = 0;
    float airTemp = 0;
    float roadTemp = 0;
    float localAngularVel[3];
    float finalFF = 0;
    float performanceMeter = 0;

    int engineBrake = 0;
    int ersRecoveryLevel = 0;
    int ersPowerLevel = 0;
    int ersHeatCharging = 0;
    int ersIsCharging = 0;
    float kersCurrentKJ = 0;

    int drsAvailable = 0;
    int drsEnabled = 0;

    float brakeTemp[4];
    float clutch = 0;

    float tyreTempI[4];
    float tyreTempM[4];
    float tyreTempO[4];

    int isAIControlled;

    float tyreContactPoint[4][3];
    float tyreContactNormal[4][3];
    float tyreContactHeading[4][3];

    float brakeBias = 0;

    float localVelocity[3];

    int P2PActivations = 0;
    int P2PStatus = 0;

    int currentMaxRpm = 0;

    float mz[4];
    float fx[4];
    float fy[4];
    float slipRatio[4];
    float slipAngle[4];


    int tcinAction = 0;
    int absInAction = 0;
    float suspensionDamage[4];
    float tyreTemp[4];

};

向python发送数据:

SPageFilePhysics* pfp = (SPageFilePhysics*)m_physics.mapFileBuffer;

send(connection, (char*)&pfp, sizeof(pfp), 0);

接收数据(Python):

import socket, struct

#Variables
socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
physicsFormat = 'ifffiiffffffffffffffffffffiifffifffffffffiiiiifiifffffifffffiiifffffiiff'


socket.connect(("127.0.0.1", 42579))

print("--------------DATA--------------")

data = socket.recv(4096)
print(data)
print(struct.unpack(physicsFormat, data))

Python 输出:

--------------DATA--------------
b'\x00\x00\xb0/\x9c\x02\x00\x00'
Traceback (most recent call last):
  File "c:/Users/lolamnma/Desktop/Telemtry Projects/OSIRIS_Telemetry/connect.py", line 14, in <module>
    print(struct.unpack(physicsFormat, data))
struct.error: unpack requires a buffer of 288 bytes

我的困惑是,打印出来的数据不应该不止这些吗?如果是这样,是因为它没有从游戏接收数据,并且结构内的所有值都是 0。还有为什么我会收到缓冲区错误。抱歉,我通常不会在网站上提问,但我似乎无法找到答案。任何帮助将不胜感激

编辑: 抱歉没有显示所有代码。一个简短的例子说明它的作用..

void initPhysics()
{
    TCHAR szName[] = TEXT("Local\\acpmf_physics");
    m_physics.hMapFile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(SPageFilePhysics), szName);
    if (!m_physics.hMapFile)
    {
        MessageBoxA(GetActiveWindow(), "CreateFileMapping failed", "ACCS", MB_OK);
    }
    m_physics.mapFileBuffer = (unsigned char*)MapViewOfFile(m_physics.hMapFile, FILE_MAP_READ, 0, 0, sizeof(SPageFilePhysics));
    if (!m_physics.mapFileBuffer)
    {
        MessageBoxA(GetActiveWindow(), "MapViewOfFile failed", "ACCS", MB_OK);
    }
}

老实说,我不太确定这个函数的作用。

m_physics.hMapFile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(SPageFilePhysics), szName);

我假设上述部分允许我查看存储在内存中的数据,我想从游戏中提取数据

调用此函数后,我的代码会创建一个套接字(我不包括这一位,因为我认为您不需要查看它。它是一个服务器,因此它接受与我的 python 脚本的连接并发送数据结束:

send(connection, (char*)&pfp, sizeof(SPageFilePhysics), 0);
SPageFilePhysics* pfp = (SPageFilePhysics*)m_physics.mapFileBuffer;

这会获取数据,但我也不太确定它的作用。我只知道它用游戏数据填充结构。

【问题讨论】:

  • 请提取并提供minimal reproducible example。此外,大多数强制类型转换是错误代码和可能存在错误的标志,因此请尽量避免它们。确保您至少了解为什么要制作它们!作为新用户,也可以使用tour 并阅读How to Ask
  • 您好,感谢您提供有用的信息,很抱歉您这么好心帮助我,让您久等了。我已经更新了上面的问题,希望能提供您需要的所有信息。
  • 注意 socket.recv 返回所有可用数据...这意味着它可能只收到一半的数据,因为其余的还没有还没寄!您需要循环调用它,直到至少有 288 个字节。如果你也有一些 next 结构,那么你可能有 more 超过 288 个字节。
  • 感谢您的警告。您将如何接收数据。我被困在试图解决它。 @user253751
  • @lolamnma 类似(不是 python 语法):/* only the first time */ received_data = b""; /* every time */ while(len(received_data) &lt; 288) {received_data += socket.recv(4096);} process data;

标签: python c++ sockets struct


【解决方案1】:

问题出在:

send(connection, (char*)&pfp, sizeof(pfp), 0);

您正在计算指针大小而不是数据大小。你正在发送指针值。 替换为:

send(connection, pfp, sizeof(SPageFilePhysics), 0);

【讨论】:

  • 感谢您帮助更改 sizeof 工作,但将其更改为 pfp 而不是 (char*)&pfp 给了我“SPageFilePhysics 类型的参数与 const char * 类型的参数不兼容”。
  • pfp 是 SPageFilePhysics 还是 SPageFilePhysics*?
  • SPageFilePhysics* .. 抱歉,我在 C++ 中最挣扎的一件事是理解指针和引用。我对他们很困惑。
  • 请参阅我对上述问题的评论。您的类型转换被破坏了,这可能是导致此问题和其他问题的原因,但是如果没有全貌就很难判断。
  • 尝试:send(connection, (void*)pfp, sizeof(SPageFilePhysics), 0)
猜你喜欢
  • 1970-01-01
  • 2022-10-24
  • 2020-05-11
  • 2021-10-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-02
相关资源
最近更新 更多